[cdo] 11/16: New upstream 1.7.2

Alastair McKinstry mckinstry at moszumanska.debian.org
Thu Aug 11 11:15:24 UTC 2016


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

mckinstry pushed a commit to branch debian/master
in repository cdo.

commit 03c5fa6571bf13337fc18a26d1ffec688bdec53e
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Sun Jul 3 12:21:22 2016 +0100

    New upstream 1.7.2
---
 ChangeLog                              |  108 ++
 Makefile.in                            |    2 -
 NEWS                                   |   22 +
 OPERATORS                              |   15 +-
 cdo.settings.in                        |    8 +-
 cdo.spec                               |    2 +-
 config/default                         |  140 +-
 configure                              |  818 ++++------
 configure.ac                           |    7 +-
 contrib/Makefile.am                    |   20 +-
 contrib/Makefile.in                    |   22 +-
 contrib/cdoCompletion.bash             |  783 +++++++++-
 contrib/cdoCompletion.tcsh             |  783 +++++++++-
 contrib/cdoCompletion.zsh              |  783 +++++++++-
 contrib/makecompl.rb                   |   15 +-
 doc/cdo.pdf                            |  Bin 2652027 -> 2658585 bytes
 doc/cdo_eca.pdf                        |  Bin 213128 -> 214623 bytes
 doc/cdo_magics.pdf                     |  Bin 829844 -> 829846 bytes
 doc/cdo_refcard.pdf                    |  Bin 91624 -> 92975 bytes
 libcdi/ChangeLog                       |   40 +
 libcdi/Makefile.am                     |    6 +
 libcdi/Makefile.in                     |   12 +-
 libcdi/app/Makefile.am                 |    5 +
 libcdi/app/Makefile.in                 |   15 +-
 libcdi/app/cdi.c                       |   15 +-
 libcdi/app/printinfo.h                 |  168 ++-
 libcdi/cdi.settings.in                 |    8 -
 libcdi/config/config.guess             |  325 ++--
 libcdi/config/config.sub               |   79 +-
 libcdi/config/default                  |   53 +-
 libcdi/configure                       |  771 +++-------
 libcdi/configure.ac                    |    2 +-
 libcdi/doc/cdi_cman.pdf                |  Bin 333778 -> 335148 bytes
 libcdi/doc/cdi_fman.pdf                |  Bin 362370 -> 363677 bytes
 libcdi/examples/Makefile.am            |    6 +-
 libcdi/examples/Makefile.in            |   17 +-
 libcdi/examples/pio/Makefile.am        |    5 +
 libcdi/examples/pio/Makefile.in        |   17 +-
 libcdi/interfaces/Makefile.am          |    6 +-
 libcdi/interfaces/Makefile.in          |   12 +-
 libcdi/m4/acx_options.m4               |  133 +-
 libcdi/src/Makefile.am                 |    2 +
 libcdi/src/Makefile.in                 |   10 +-
 libcdi/src/binary.h                    |    2 -
 libcdi/src/calendar.c                  |   91 +-
 libcdi/src/cdf.c                       |   30 +-
 libcdi/src/cdf_read.c                  |   50 +-
 libcdi/src/cdi.h                       |   32 +
 libcdi/src/cdi.inc                     |   66 +-
 libcdi/src/cdiFortran.c                |   10 +
 libcdi/src/cdi_int.c                   |    2 +-
 libcdi/src/cdilib.c                    | 2573 ++++++++++++++++++--------------
 libcdi/src/cdipio.inc                  |    4 +-
 libcdi/src/cgribexlib.c                |  271 ++--
 libcdi/src/config.h.in                 |   27 +-
 libcdi/src/dtypes.h                    |    6 +-
 libcdi/src/grb_write.c                 |    3 +-
 libcdi/src/gribapi_utilities.c         |   38 +-
 libcdi/src/grid.c                      |  624 ++++----
 libcdi/src/grid.h                      |   14 +-
 libcdi/src/mo_cdi.f90                  |  152 ++
 libcdi/src/pio_client.c                |    2 +-
 libcdi/src/pio_comm.c                  |   21 +-
 libcdi/src/pio_comm.h                  |    2 +-
 libcdi/src/pio_interface.c             |    9 +-
 libcdi/src/pio_mpi_fw_at_reblock.c     |   10 +-
 libcdi/src/pio_posixnonb.c             |   64 +-
 libcdi/src/pio_rpc.c                   |    6 +-
 libcdi/src/pio_rpc.h                   |   28 +-
 libcdi/src/pio_server.c                |   60 +-
 libcdi/src/pio_util.c                  |    4 +-
 libcdi/src/pio_util.h                  |    4 +
 libcdi/src/pkgconfig/cdi.pc.in         |    7 +-
 libcdi/src/pkgconfig/cdipio.pc.in      |    7 +-
 libcdi/src/stream.c                    |   97 +-
 libcdi/src/stream_cdf.c                | 1638 ++++++++++----------
 libcdi/src/stream_cgribex.c            |  326 ++--
 libcdi/src/stream_grb.c                |   40 +-
 libcdi/src/stream_gribapi.c            |  510 ++++---
 libcdi/src/subtype.h                   |    6 +-
 libcdi/src/timebase.c                  |   70 +-
 libcdi/src/util.c                      |    8 +
 libcdi/src/vlist_var.c                 |   27 +-
 libcdi/src/zaxis.c                     |  138 +-
 libcdi/src/zaxis.h                     |    2 +
 libcdi/tests/Makefile.am               |    5 +
 libcdi/tests/Makefile.in               |   31 +-
 m4/acx_options.m4                      |  141 +-
 src/Afterburner.c                      |  166 ++-
 src/Arith.c                            |    2 +
 src/Arithdays.c                        |    4 +-
 src/CDItest.c                          |   49 +-
 src/CMOR.c                             |  479 +++---
 src/Cat.c                              |    3 +-
 src/Collgrid.c                         |   50 +-
 src/Copy.c                             |    5 +-
 src/Deltime.c                          |   37 +-
 src/Derivepar.c                        |  132 +-
 src/Diff.c                             |   54 +-
 src/Distgrid.c                         |   56 +-
 src/Duplicate.c                        |   44 +-
 src/EOFs.c                             |    4 +-
 src/EcaIndices.c                       |  145 +-
 src/Enlarge.c                          |   43 +-
 src/Enlargegrid.c                      |   43 +-
 src/Ensstat.c                          |    6 +-
 src/Ensstat3.c                         |   12 +-
 src/Ensval.c                           |   10 +-
 src/Exprf.c                            |    8 +-
 src/FC.c                               |   45 +-
 src/Filedes.c                          |   27 +-
 src/Fillmiss.c                         |    5 +-
 src/Filter.c                           |   27 +-
 src/Gradsdes.c                         |    5 +-
 src/Harmonic.c                         |    2 +-
 src/Importcmsaf.c                      |    2 +-
 src/Info.c                             |   10 +-
 src/Input.c                            |   73 +-
 src/Intgrid.c                          |   55 +-
 src/Intlevel.c                         |   81 +-
 src/Intlevel3d.c                       |  116 +-
 src/Invertlev.c                        |    9 +-
 src/Isosurface.c                       |    2 +-
 src/Kvl.c                              |    6 +-
 src/Maggraph.c                         |    2 +-
 src/Magplot.c                          |   26 +-
 src/Magvector.c                        |   17 +-
 src/Makefile.am                        |   12 +-
 src/Makefile.in                        |  179 +--
 src/MapReduce.c                        |  220 +++
 src/Math.c                             |   46 +-
 src/Merge.c                            |    9 +-
 src/Mergetime.c                        |   13 +-
 src/Monarith.c                         |    2 +-
 src/Mrotuvb.c                          |  111 +-
 src/Ninfo.c                            |   35 +-
 src/Output.c                           |   39 +-
 src/Outputgmt.c                        |    2 +-
 src/Pressure.c                         |  139 +-
 src/Remap.c                            |  120 +-
 src/Remapeta.c                         |  215 ++-
 src/SSOpar.c                           |  993 ------------
 src/Select.c                           |  911 +++--------
 src/Seloperator.c                      |   31 +-
 src/Seltime.c                          |  100 +-
 src/Selvar.c                           |   91 +-
 src/Setgrid.c                          |   83 +-
 src/Setpartab.c                        |   80 +-
 src/Setrcaname.c                       |   28 +-
 src/Settime.c                          |   63 +-
 src/Sinfo.c                            |    6 +-
 src/Smooth.c                           |  516 +++++++
 src/Smooth9.c                          |  311 ----
 src/Spectral.c                         |   52 +-
 src/Split.c                            |    5 +-
 src/Splitrec.c                         |   26 +-
 src/Splitsel.c                         |   26 +-
 src/Splittime.c                        |    3 +-
 src/Splityear.c                        |    9 +-
 src/Tee.c                              |   36 +-
 src/Templates.c                        |   11 +-
 src/Timedt.c                           |    4 +-
 src/Timstat.c                          |    2 +-
 src/Vargen.c                           |   89 +-
 src/Verifygrid.c                       | 1478 +++++++-----------
 src/Vertintap.c                        |  247 ++-
 src/Vertintml.c                        |  162 +-
 src/Wind.c                             |   49 +-
 src/XTimstat.c                         |    2 +-
 src/YAR.c                              |   46 +-
 src/Ydrunpctl.c                        |    4 +-
 src/Ydrunstat.c                        |    2 +-
 src/after_vertint.c                    |  179 +--
 src/after_vertint.h                    |    6 +-
 src/afterburnerlib.c                   |  230 +--
 src/cdo.c                              |   54 +-
 src/cdo_history.c                      |    4 +-
 src/cdo_int.h                          |   23 +-
 src/cdo_vlist.c                        |  207 ++-
 src/clipping/geometry.h                |    8 +
 src/clipping/intersection.c            |   24 +-
 src/commandline.c                      |   68 +-
 src/config.h.in                        |   18 +-
 src/datetime.c                         |  124 +-
 src/datetime.h                         |   22 +-
 src/exception.c                        |   64 +-
 src/expr.c                             |  103 +-
 src/features.c                         |   19 +-
 src/field.h                            |    4 +-
 src/fieldc.c                           |    2 +-
 src/gradsdeslib.c                      |   63 +-
 src/grid.c                             |  140 +-
 src/grid.h                             |    8 +-
 src/grid_gme.c                         |  111 +-
 src/grid_search.c                      |  214 ++-
 src/grid_search.h                      |   20 +-
 src/griddes.c                          |  164 +-
 src/interpol.c                         |  169 ++-
 src/job.c                              |   31 +-
 src/juldate.c                          |   16 +-
 src/kdtreelib/kdtree_cartesian.c       |  115 +-
 src/merge_sort2.c                      |   10 +-
 src/modules.c                          |   30 +-
 src/namelist.c                         |    4 +
 src/operator_help.h                    |  257 +++-
 src/percentiles.c                      |    2 +-
 src/pmlist.c                           |  366 +++++
 src/pmlist.h                           |   88 ++
 src/printinfo.h                        |  161 +-
 src/process.c                          |    2 +-
 src/pstream.c                          |  666 +++++----
 src/pthread_debug.c                    |   11 +-
 src/readline.c                         |    9 +-
 src/remap.h                            |   17 +-
 src/remap_conserv.c                    |   22 +-
 src/remap_conserv_scrip.c              |    8 +-
 src/remap_distwgt.c                    |   83 +-
 src/remap_scrip_io.c                   |    8 +-
 src/remaplib.c                         |   41 +-
 src/remapsort.c                        |    8 +-
 src/userlog.c                          |   43 +-
 src/uthash.h                           |  966 ++++++++++++
 src/util.c                             |  123 +-
 src/util.h                             |    6 +
 src/zaxis.c                            |   21 +-
 test/Afterburner.test.in               |    4 +-
 test/Arith.test.in                     |   84 +-
 test/{Arith.test.in => Arithc.test.in} |    4 +-
 test/Cat.test.in                       |    4 +-
 test/Collgrid.test.in                  |    4 +-
 test/Copy_netcdf.test.in               |    4 +-
 test/Detrend.test.in                   |    4 +-
 test/Enspctl.test.in                   |   12 +-
 test/Ensstat.test.in                   |   12 +-
 test/Expr.test.in                      |    4 +-
 test/File.test.in                      |   66 +-
 test/Fldpctl.test.in                   |    4 +-
 test/Fldstat.test.in                   |    4 +-
 test/Genweights.test.in                |   46 +-
 test/Gradsdes.test.in                  |    4 +-
 test/Gridarea.test.in                  |   22 +-
 test/Makefile.am                       |    8 +-
 test/Makefile.in                       |   32 +-
 test/MapReduce.test.in                 |   50 +
 test/Ninfo.test.in                     |   61 +
 test/Read_grib.test.in                 |    8 +-
 test/Read_netcdf.test.in               |    4 +-
 test/Remap.test.in                     |   38 +-
 test/Select.test.in                    |    4 +-
 test/Spectral.test.in                  |    4 +-
 test/Timstat.test.in                   |    4 +-
 test/Vertint.test.in                   |    4 +-
 test/Ymonstat.test.in                  |    4 +-
 test/data/Makefile.am                  |   12 +-
 test/data/Makefile.in                  |   14 +-
 test/data/arith1.srv                   |  Bin 0 -> 5184 bytes
 test/data/arithadd_ref                 |  Bin 0 -> 5184 bytes
 test/data/arithdiv_ref                 |  Bin 0 -> 5184 bytes
 test/data/arithmask.srv                |  Bin 0 -> 864 bytes
 test/data/arithmul_ref                 |  Bin 0 -> 5184 bytes
 test/data/arithsub_ref                 |  Bin 0 -> 5184 bytes
 test/data/expr1.srv                    |  Bin 0 -> 6048 bytes
 test/data/grib_testfile03.grb          |  Bin 0 -> 71864 bytes
 test/data/grib_testfile03_info_ref     |    2 +
 test/data/grib_testfile03_sinfo_ref    |   12 +
 test/data/griddes.icon_cell            |  174 +++
 test/data/griddes.r18x9                |  199 +++
 test/data/icon_cell_grid               |  Bin 0 -> 7636 bytes
 test/data/r18x9_grid                   |  Bin 0 -> 408 bytes
 test/data/tsformat1_ref                |  Bin 0 -> 312 bytes
 test/threads.test.in                   |   10 +-
 test/tsformat.test.in                  |   94 ++
 test/wildcard.test.in                  |    4 +-
 273 files changed, 15257 insertions(+), 11892 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 239359e..b0fdeb5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,111 @@
+2016-06-28  Uwe Schulzweida
+
+	* using CDI library version 1.7.2
+	* Version 1.7.2 released
+
+2016-06-28  Uwe Schulzweida
+
+	* replace option -Q by --sort
+	* delete, delcode, delname: wrong variable check (bug fix)
+
+2016-06-27  Uwe Schulzweida
+
+	* round doesn't work as expected, replaced by lround()
+	* nint, expr(nint()): replace round by lround() (bug fix)
+
+2016-06-21  Uwe Schulzweida
+
+	* Renamed operator setpartab to setcodetab
+	* Renamed operator pardes to codetab
+
+2016-06-13  Uwe Schulzweida
+
+	* mul: wrong result for missval*0 (bug fix)
+	* expr: nmiss lost for time constant fields (bug fix)
+
+2016-06-07  Uwe Schulzweida
+
+	* select: file structure may change with time constant variables (bug fix)
+	* select: wrong result with time constant 3D variables (bug fix)
+
+2016-06-02  Uwe Schulzweida
+
+	* input: added optional zaxis parameter
+
+2016-05-27   Asela Rajapakse
+
+	* New operator verifygrid - Verify grids
+
+2016-05-25  Uwe Schulzweida
+
+	* CDO_CommandLine: changed from fixed size of 1024 to dynamic size
+	* uv2dv: ignore GRIB2 parameter id
+
+2016-05-20  Uwe Schulzweida
+
+	* Select: check level only if no vars selected
+
+2016-04-28  Uwe Schulzweida
+
+	* readline: added support for DOS text files (\r\n)
+
+2016-04-26  Uwe Schulzweida
+
+	* New operator: smooth - Smooth grid points
+
+2016-04-25  Uwe Schulzweida
+
+	* New operator: ap2hl - Air pressure to height level interpolation
+	* Added option --cmor to write CMOR conform NetCDF output
+	* setpartabn - added support for character # and ! deactivate line in table file
+
+2016-04-19  Uwe Schulzweida
+
+	* Adjust date/time by -1 second if the verification time is equal to upper time bound
+
+2016-04-13  Uwe Schulzweida
+
+	* gridsearch_qnearest: removed range check (bug fix)
+	* grid_search_nbr: set range0 to SQR(search_radius) (bug fix)
+
+2016-04-11  Uwe Schulzweida
+
+	* Magplot: set NAN missvals to -9e33 [Bug: #6677]
+
+2016-04-08  Uwe Schulzweida
+
+	* afterburner: seg. fault with data on half level (bug fix) [report: Monika Esch]
+
+2016-04-04  Ralf Mueller
+
+        * New operators: ngrids, ngridpoints - Show number of grids/gridpoints per variable
+
+2016-04-02  Uwe Schulzweida
+
+	* Fix typo in eca_sdii code [Bug #6655]
+
+2016-03-27  Uwe Schulzweida
+
+ 	* clipping/geometry.h::get_angle: replace round() by lround()
+
+2016-03-25  Uwe Schulzweida/Ralf Mueller
+
+	* OpenMP installation error [Bug #6523]
+	* New operator: reducegrid - Select gridpoints wrt. given mask
+
+2016-03-18  Uwe Schulzweida
+
+	* New operator: settbounds - Set time bounds settbounds - Set time bounds
+
+2016-03-17  Uwe Schulzweida
+
+	* expr: renamed function log() to ln()
+	* eca_cdd, eca_cwd: Added support to choose the amount of days
+
+2016-03-05  Uwe Schulzweida
+
+	* merge, mergetime: option -s doesn't work correctly (bug fix)
+
 2016-02-25  Uwe Schulzweida
 
 	* using CDI library version 1.7.1
diff --git a/Makefile.in b/Makefile.in
index a0347df..bab544c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -320,8 +320,6 @@ UDUNITS_LDFLAGS = @UDUNITS_LDFLAGS@
 USER_NAME = @USER_NAME@
 VERSION = @VERSION@
 XML2_LIBS = @XML2_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
diff --git a/NEWS b/NEWS
index 3bd9eb9..f4a556c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,26 @@
 CDO NEWS
 --------
 
+Version 1.7.2 (28 June 2016):
+
+   New operators:
+     * smooth: Smooth grid points
+     * ap2hl: Air pressure to height level interpolation
+     * ngrids: Show number of grids
+     * ngridpoints: Show number of gridpoints per variable
+     * reducegrid: Select gridpoints wrt. given mask
+     * settbounds: Set time bounds
+   Changed operators:
+     * input: added optional zaxis parameter
+     * setpartab: renamed to setcodetab
+     * pardes: renamed to codetab
+   Fixed bugs:
+     * Error reading Gaussian reduced GRIB files [Bug #6780 #6819]
+     * Installation error with OpenMP [Bug #6523]
+     * mul: wrong result for missval*0 (bug was introduced in 1.7.1)
+     * nint: wrong result (replaced round() by lround())
+     * shaded, contour, grfill: set NAN missvals to -9e33 [Bug: #6677]
+
 Version 1.7.1 (25 February 2016):
 
    New features:
@@ -13,6 +33,8 @@ Version 1.7.1 (25 February 2016):
      * contour: Contour plot
      * shaded: Shaded contour plot
      * grfill: Shaded gridfill plot
+     * vector: Lat/Lon vector plot
+     * graph: Line graph plot
      * gmtxyz: Output GMT xyz format to create contour plots with the GMT module pscontour.
      * gmtcells: Output GMT multiple segment format to create shaded gridfill plots with psxy.
    Fixed bugs:
diff --git a/OPERATORS b/OPERATORS
index 11a5dd5..999dfcd 100644
--- a/OPERATORS
+++ b/OPERATORS
@@ -20,6 +20,8 @@ Operator catalog:
    Ninfo         nmon            Number of months
    Ninfo         ndate           Number of dates
    Ninfo         ntime           Number of timesteps
+   Ninfo         ngridpoints     Number of gridpoints
+   Ninfo         ngrids          Number of horizontal grids
    Showinfo      showformat      Show file format
    Showinfo      showcode        Show code numbers
    Showinfo      showname        Show variable names
@@ -31,7 +33,8 @@ Operator catalog:
    Showinfo      showdate        Show date information
    Showinfo      showtime        Show time information
    Showinfo      showtimestamp   Show timestamp
-   Filedes       pardes          Parameter description
+   Filedes       partab          Parameter table
+   Filedes       codetab         Parameter code table
    Filedes       griddes         Grid description
    Filedes       zaxisdes        Z-axis description
    Filedes       vct             Vertical coordinate table
@@ -99,6 +102,7 @@ Operator catalog:
    Cond2         ifthenelse      If then else
    Condc         ifthenc         If then constant
    Condc         ifnotthenc      If not then constant
+   MapReduce     reducegrid      Reduce input file variables to locations, where mask is non-zero.
 -------------------------------------------------------------
    Comparison
 -------------------------------------------------------------
@@ -119,7 +123,7 @@ Operator catalog:
 -------------------------------------------------------------
    Setpartab     setpartabp      Set parameter table
    Setpartab     setpartabn      Set parameter table
-   Set           setpartab       Set parameter table
+   Set           setcodetab      Set parameter code table
    Set           setcode         Set code number
    Set           setparam        Set parameter identifier
    Set           setname         Set variable name
@@ -133,6 +137,7 @@ Operator catalog:
    Settime       setyear         Set year
    Settime       settunits       Set time units
    Settime       settaxis        Set time axis
+   Settime       settbounds      Set time bounds
    Settime       setreftime      Set reference time
    Settime       setcalendar     Set calendar
    Settime       shifttime       Shift timesteps
@@ -466,7 +471,8 @@ Operator catalog:
    Remapeta      remapeta        Remap vertical hybrid level
    Vertint       ml2pl           Model to pressure level interpolation
    Vertint       ml2hl           Model to height level interpolation
-   Vertintap     ap2pl           Model to pressure level interpolation
+   Vertintap     ap2pl           Air pressure to pressure level interpolation
+   Vertintap     ap2hl           Air pressure to height level interpolation
    Intlevel      intlevel        Linear level interpolation
    Intlevel3d    intlevel3d      Linear level interpolation onto a 3d vertical coordinate
    Intlevel3d    intlevelx3d     like intlevel3d but with extrapolation
@@ -513,7 +519,8 @@ Operator catalog:
    Filter        highpass        Highpass filtering
    Gridcell      gridarea        Grid cell area
    Gridcell      gridweights     Grid cell weights
-   Smooth9       smooth9         9 point smoothing
+   Smooth        smooth          Smooth grid points
+   Smooth        smooth9         9 point smoothing
    Replacevalues setvals         Set list of old values to new values
    Replacevalues setrtoc         Set range to constant
    Replacevalues setrtoc2        Set range to constant others to constant2
diff --git a/cdo.settings.in b/cdo.settings.in
index bf0a1bc..973b390 100644
--- a/cdo.settings.in
+++ b/cdo.settings.in
@@ -22,10 +22,6 @@
   "threads"    : {
     "lib"      : "@THREADS_LIBS@",
     "include"  : "@THREADS_INCLUDE@"
-  },
-  "zlib"       : {
-    "lib"      : "@ZLIB_LIBS@",
-  },
   "szlib"      : {
     "lib"      : "@SZLIB_LIBS@",
     "include"  : "@SZLIB_INCLUDE@"
@@ -46,6 +42,10 @@
     "lib"      : "@PROJ_LDFLAGS@",
     "include"  : "@PROJ_INCLUDE@"
   },
+  "magics"       : {
+    "lib"      : "@MAGICS_LIBS@",
+    "include"  : "@MAGICS_INCLUDE@"
+  },
   "USER_NAME"          : "@USER_NAME@",
   "HOST_NAME"          : "@HOST_NAME@",
   "SYSTEM_TYPE"        : "@SYSTEM_TYPE@"
diff --git a/cdo.spec b/cdo.spec
index 6f6566e..ae1fd3d 100644
--- a/cdo.spec
+++ b/cdo.spec
@@ -4,7 +4,7 @@
 
 Name:           cdo
 #BuildRequires:  
-Version:        1.7.1
+Version:        1.7.2
 Release:        1
 Summary:        Climate Data Operators
 License:        GNU GENERAL PUBLIC LICENSE Version 2, June 1991
diff --git a/config/default b/config/default
index d2b1912..36a86a6 100755
--- a/config/default
+++ b/config/default
@@ -31,7 +31,7 @@ case "${HOSTNAME}" in
     bailung*|d133*|d134*)
         CDOLIBS="--enable-nearpt3 \
                  --with-fftw3 \
-                 --with-grib_api=$HOME/local/grib_api-1.13.1 \
+                 --with-grib_api=$HOME/local/grib_api-1.14.7 \
                  --with-netcdf=$HOME/local/netcdf-c-4.3.3.1-threadsafe \
                  --with-hdf5=$HOME/local/hdf5-1.8.15-threadsafe \
                  --with-udunits2=/opt/local \
@@ -111,11 +111,35 @@ case "${HOSTNAME}" in
 	  ${CONFPATH}configure --prefix=$HOME/local \
                     --enable-maintainer-mode \
                     $CDOLIBS \
-	            CC=gcc CFLAGS="-g -std=c11 -pipe -Wall -Wpointer-arith -Wwrite-strings -W -Wfloat-equal -pedantic -O3 -march=native -fstack-protector -funsigned-char -Wa,-q"
+	            CC=gcc CFLAGS="-g -std=c11 -pipe -Wall -Wpointer-arith -Wwrite-strings -W -Wfloat-equal -pedantic -O3 -march=native -Wa,-q -fstack-protector -funsigned-char"
 #                    --with-libxml2=/usr \
 #                    --with-magics=/Users/m214003/local/Magics-2.18.14nio \
         fi
 	;;
+    cdo4windows-cyg)
+        CDOLIBS="--with-netcdf=/usr/local \
+                 --with-hdf5=/usr/local \
+                 --with-udunits2=/usr \
+                 --with-proj=/usr"
+
+        if  test "$COMP" = g++ ; then
+	  ${CONFPATH}configure --prefix=/usr/local \
+                    --program-suffix=-g++ \
+                    --enable-cxx \
+                    --enable-maintainer-mode \
+                    $CDOLIBS \
+	            CC=g++ CFLAGS="-g -Wall -O2 -DPIC -pie -mwindows" \
+                    LDFLAGS='-L/usr/local/lib' \
+                    LIBS='-lpthread -lm -lcurl -lhdf5_hl -lhdf5 -lz  -lsz -laec -ldl'
+        else
+	  ${CONFPATH}configure --prefix=$HOME/local \
+                    --enable-maintainer-mode \
+                    $CDOLIBS \
+	            CC=gcc CFLAGS="-g -Wall -O2 -DPIC -pie -mwindows" \
+                    LDFLAGS='-L/usr/local/lib' \
+                    LIBS='-lpthread -lm -lcurl -lhdf5_hl -lhdf5 -lz  -lsz -laec -ldl'
+        fi
+	;;
     daint*)
         if  test "$COMP" = icc ; then
           CDOLIBS="--with-netcdf=/opt/cray/netcdf/4.3.3.1/INTEL/14.0"
@@ -146,7 +170,7 @@ case "${HOSTNAME}" in
                  --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"
+                 --with-proj=/sw/squeeze-x64/proj-4.7.0 LIBS=-lz"
 
         if  test "$COMP" = icpc ; then
           ${CONFPATH}configure --enable-cxx --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
@@ -162,6 +186,16 @@ case "${HOSTNAME}" in
           ${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
                     $CDOLIBS \
 	            CC=pgcc CFLAGS="-g -fast"
+        elif  test "$COMP" = clang ; then
+          ${CONFPATH}configure              --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
+                    --with-fftw3 \
+                    $CDOLIBS \
+	            CC=clang CXX=clang++ CFLAGS="-g -O2"
+        elif  test "$COMP" = clang++ ; then
+          ${CONFPATH}configure --enable-cxx --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
+                    --with-fftw3 \
+                    $CDOLIBS \
+	            CC=clang CXX=clang++ CFLAGS="-g -O2"
         elif  test "$COMP" = g++ ; then
 	  ${CONFPATH}configure --enable-cxx \
                     $CDOLIBS \
@@ -181,6 +215,7 @@ case "${HOSTNAME}" in
                  --with-szlib=/sw/rhel6-x64/sys/szip-2.1-gcc48 \
                  --with-udunits2=/sw/rhel6-x64/util/udunits-2.2.17-gcc48 \
                  --with-proj=/sw/rhel6-x64/graphics/proj4-4.9.1-gcc48"
+#                 --with-magics=/sw/rhel6-x64/graphics/magicsxx-2.18.15-gfxonly-gcc48 \
 #                 --with-cmor=/sw/rhel6-x64/cmor-2.9.2-shared-gcc48 \
 
         if  test "$COMP" = icc ; then
@@ -196,7 +231,7 @@ case "${HOSTNAME}" in
           ${CONFPATH}configure --prefix=$HOME/local \
                     --with-fftw3 \
                     $CDOLIBS \
-                    CC=gcc CFLAGS='-g -Wall -O3 -march=native'
+                    CC=gcc CFLAGS='-g -Wall -O3 -march=native -mavx2'
 	fi
 	;;
 # x86_64-unknown-linux-gnu
@@ -231,27 +266,87 @@ case "${HOSTNAME}" in
 	;;
 # x86_64-archlinux
     luthien*)
+      case "$COMP" in
+      gcc|clang)
+ 	${CONFPATH}configure --prefix=$HOME/local \
+                    --program-suffix=-dev \
+                    --enable-maintainer-mode \
+                    --enable-data \
+	            --with-netcdf \
+	              --with-hdf5 \
+                     --with-szlib \
+                  --with-grib_api \
+                  --with-udunits2 \
+                  --with-grib_api \
+                  --with-fftw3    \
+                  --with-proj     \
+                      --with-pic  \
+                      CC=$COMP CFLAGS="-g -Wall -O3" LIBS="-lopenjpeg" LDFLAGS='-lelf -v'
+        ;;
+      g++|clang++)
  	${CONFPATH}configure --prefix=$HOME/local \
                     --program-suffix=-dev \
                     --enable-maintainer-mode \
+                    --enable-data \
+                    --enable-cxx  \
 	            --with-netcdf \
 	              --with-hdf5 \
                      --with-szlib \
                   --with-grib_api \
                   --with-udunits2 \
-                  --with-proj \
-                      --with-pic \
-                      CC=gcc CFLAGS="-g -Wall -O2 -DWITH_DATA" LIBS=-lopenjpeg
+                  --with-grib_api \
+                  --with-fftw3    \
+                  --with-proj     \
+                      --with-pic  \
+                      CC=$COMP CFLAGS="-g -Wall -O2" LIBS=-lopenjpeg
 	;;
+      esac
+    ;;
+# standard workstations at MPI-M debian jessie
+    mpipc149)
+      CDOLIBS="--prefix=`pwd`/build \
+              --enable-maintainer-mode \
+              --with-netcdf=/sw/jessie-x64/netcdf-4.3.3.1-gccsys \
+              --with-hdf5=/sw/jessie-x64/hdf5-1.8.16-gccsys/ \
+              --with-szlib=/sw/jessie-x64/szip-2.1-gccsys \
+              --with-udunits2=/sw/jessie-x64/udunits-2.2.20-gccsys \
+              --enable-ruby --enable-swig --enable-python "
+      case "$COMP" in
+        gcc)
+          ${CONFPATH}configure \
+            $CDOLIBS \
+            CC=gcc CFLAGS="-g -Wall -W -Wfloat-equal -pedantic -O2" LIBS='-lm  -lpthread '
+          ;;
+        g++) # jessie used gcc 6.1.1
+          ${CONFPATH}configure \
+            $CDOLIBS \
+            --enable-cxx \
+            CC=gcc CXX=g++ CFLAGS="-std=c++11 -g -Wall -W -Wfloat-equal -pedantic -O2" LIBS='-lm  -lpthread '
+          ;;
+        clang)
+          ${CONFPATH}configure \
+            $CDOLIBS \
+            --disable-openmp \
+            CC=/sw/jessie-x64/util/clang+llvm-3.8.0/bin/clang CXX=/sw/jessie-x64/util/clang+llvm-3.8.0/bin/clang++
+        ;;
+        clang++) # recent clang-3.8
+          ${CONFPATH}configure \
+            $CDOLIBS \
+            --disable-openmp \
+            --enable-cxx \
+            CC=/sw/jessie-x64/util/clang+llvm-3.8.0/bin/clang CXX=/sw/jessie-x64/util/clang+llvm-3.8.0/bin/clang++
+        ;;
+      esac
+      ;;
 # standard workstations at MPI-M x86_64-lenny
     mpipc* )
 	${CONFPATH}configure \
                --prefix=`pwd`/build \
                --enable-maintainer-mode \
-               --with-netcdf='/sw/lenny-x64/netcdf-latest-gccsys' \
-               --with-hdf5='/sw/lenny-x64/hdf5-latest' \
-               --with-szlib='/sw/lenny-x64/szip-latest' \
-               --with-proj='/sw/lenny-x64/proj-latest' \
+               --with-netcdf='/sw/squeeze-x64/netcdf-latest-gccsys' \
+               --with-hdf5='/sw/squeeze-x64/hdf5-latest' \
+               --with-szlib='/sw/squeeze-x64/szip-latest' \
+               --with-proj='/sw/squeeze-x64/proj-latest' \
                --enable-ruby --enable-swig --enable-python \
 	           CC=gcc CFLAGS="-g -Wall -W -Wfloat-equal -pedantic -O2"
         ;;
@@ -260,7 +355,6 @@ case "${HOSTNAME}" in
  	  ${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/etch-ia32 \
 	            --with-netcdf=/sw/etch-ia32/netcdf-4.1.1-gcc \
 	            --with-hdf5=/sw/etch-ia32/hdf5-1.8.4-threadsafe \
-                    --with-zlib=/sw/etch-ia32/zlib-1.2.3 \
                     --with-szlib=/sw/etch-ia32/szip-2.1 \
                     --withroj=/sw/etch-ia32/proj-4.6.0 \
 	            --enable-all-static CC=icc CFLAGS="-g -fast -openmp" AR=xiar LD=xild
@@ -303,7 +397,6 @@ case "${HOSTNAME}" in
                     --with-grib_api=/sw/centos58-x64/grib_api-1.12.3 \
                     --with-netcdf=/sw/centos58-x64/netcdf-4.2.1.1 \
                     --with-szlib=/sw/centos58-x64/szip-2.1 \
-                    --with-zlib=/usr \
 	            CC=gcc CFLAGS="-g -Wall -O3"
 	;;
 # powerpc-ibm-aix5.3.0.0
@@ -327,6 +420,27 @@ 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"
 	;;
+# win7 based cygwin virtual machine
+    cdo4windows-cyg)
+        if  test "$COMP" = gcc ; then
+          ${CONFPATH}configure \
+                      --with-netcdf \
+                      --with-hdf5 \
+                      --with-proj \
+                      --with-fftw3 \
+                      --with-udunits \
+                      CC=gcc CFLAGS='-g -Wall -O3'
+        elif  test "$COMP" = g++ ; then
+          ${CONFPATH}configure \
+                      --with-netcdf \
+                      --with-hdf5 \
+                      --with-proj \
+                      --with-fftw3 \
+                      --with-udunits \
+                      --enable-cxx \
+                      CC=gcc CXX=g++ CFLAGS='-g -Wall -O3' CXXFLAGS='-g -Wall -O3'
+        fi
+        ;;
     *)
 	echo "configuration for hostname $HOSTNAME not found!"
 	;;
diff --git a/configure b/configure
index 116e78f..ca8b3d0 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.7.1.
+# Generated by GNU Autoconf 2.68 for cdo 1.7.2.
 #
 # Report bugs to <http://mpimet.mpg.de/cdo>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='cdo'
 PACKAGE_TARNAME='cdo'
-PACKAGE_VERSION='1.7.1'
-PACKAGE_STRING='cdo 1.7.1'
+PACKAGE_VERSION='1.7.2'
+PACKAGE_STRING='cdo 1.7.2'
 PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdo'
 PACKAGE_URL=''
 
@@ -640,8 +640,6 @@ XML2_LIBS
 MAGICS_INCLUDE
 MAGICS_ROOT
 MAGICS_LIBS
-UDUNITS_INCLUDE
-UDUNITS_LDFLAGS
 CURL_INCLUDE
 CURL_LDFLAGS
 PROJ_INCLUDE
@@ -655,6 +653,8 @@ ENABLE_GRIBAPI
 GRIB_API_LIBS
 GRIB_API_INCLUDE
 CMOR_LIBS
+UDUNITS_INCLUDE
+UDUNITS_LDFLAGS
 NETCDF_LIBS
 NETCDF_INCLUDE
 NETCDF_ROOT
@@ -668,8 +668,6 @@ HDF5_INCLUDE
 HDF5_ROOT
 SZLIB_LIBS
 SZLIB_INCLUDE
-ZLIB_LIBS
-ZLIB_INCLUDE
 THREADS_LIBS
 THREADS_INCLUDE
 ENABLE_THREADS
@@ -822,10 +820,10 @@ enable_openmp
 enable_largefile
 enable_data
 with_threads
-with_zlib
 with_szlib
 with_hdf5
 with_netcdf
+with_udunits2
 with_cmor
 with_grib_api
 enable_grib
@@ -836,7 +834,6 @@ enable_ieg
 with_fftw3
 with_proj
 with_curl
-with_udunits2
 with_magics
 with_libxml2
 enable_cdi_lib
@@ -1398,7 +1395,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.7.1 to adapt to many kinds of systems.
+\`configure' configures cdo 1.7.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1468,7 +1465,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of cdo 1.7.1:";;
+     short | recursive ) echo "Configuration of cdo 1.7.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1514,17 +1511,15 @@ Optional Packages:
                         (or the compiler's sysroot if not specified).
   --with-threads=<yes/no/directory>
                           Compile + link for multithreading [default=yes]
-  --with-zlib=<yes|no|directory> (default=yes)
-                          location of ZLIB compression library (lib and
-                          include subdirs), nec. for HDF5/NETCDF4
   --with-szlib=<yes|no|directory> (default=no)
-                          location of szlib library, optional for GRIB1 and
-                          NETCDF4 compression
+                          location of szlib library, optional for GRIB1
+                          compression
   --with-hdf5=<yes|no|directory> (default=no)
-                          location of hdf5 library, NETCDF4 requires hdf5 high
-                          level interface
+                          location of HDF5 library
   --with-netcdf=<yes|no|directory> (default=no)
-                          location of netCDF library (lib and include subdirs)
+                          location of NetCDF library (lib and include subdirs)
+  --with-udunits2=<directory>
+                          Specify location of UDUNITS2 library.
   --with-cmor=<directory> Specify location of CMOR library.
   --with-grib_api=<yes|no|directory> (default=no)
                           location of GRIB_API library (lib and include
@@ -1533,8 +1528,6 @@ Optional Packages:
   --with-proj=<directory> Specify location of PROJ library for cartographic
                           projections.
   --with-curl=<directory> Specify location of CURL library.
-  --with-udunits2=<directory>
-                          Specify location of UDUNITS2 library.
   --with-magics=<yes|no|directory>
                           location of magics library (lib and include subdirs)
   --with-libxml2=<yes|no|directory>
@@ -1620,7 +1613,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-cdo configure 1.7.1
+cdo configure 1.7.2
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2213,7 +2206,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.7.1, which was
+It was created by cdo $as_me 1.7.2, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3162,7 +3155,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='cdo'
- VERSION='1.7.1'
+ VERSION='1.7.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -18324,248 +18317,7 @@ esac
 
 
 #  ----------------------------------------------------------------------
-#  Link application to ZLIB library, needed for netcdf
-ZLIB_INCLUDE=''
-ZLIB_LIBS=''
-
-# Check whether --with-zlib was given.
-if test "${with_zlib+set}" = set; then :
-  withval=$with_zlib; case "$with_zlib" in #(
-  no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB library" >&5
-$as_echo_n "checking for ZLIB library... " >&6; }
-                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; } ;; #(
-  yes) :
-    for ac_header in zlib.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_zlib_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_ZLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
-$as_echo_n "checking for library containing deflate... " >&6; }
-if ${ac_cv_search_deflate+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' z; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_deflate=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_deflate+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_deflate+:} false; then :
-
-else
-  ac_cv_search_deflate=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
-$as_echo "$ac_cv_search_deflate" >&6; }
-ac_res=$ac_cv_search_deflate
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
-
-fi
-
-                            ZLIB_LIBS=" -lz" ;; #(
-  *) :
-    ZLIB_ROOT=$with_zlib
-                          LDFLAGS="-L$ZLIB_ROOT/lib $LDFLAGS"
-                          CPPFLAGS="-I$ZLIB_ROOT/include $CPPFLAGS"
-                          for ac_header in zlib.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_zlib_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_ZLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-                          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
-$as_echo_n "checking for library containing deflate... " >&6; }
-if ${ac_cv_search_deflate+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' z; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_deflate=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_deflate+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_deflate+:} false; then :
-
-else
-  ac_cv_search_deflate=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
-$as_echo "$ac_cv_search_deflate" >&6; }
-ac_res=$ac_cv_search_deflate
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
-
-fi
-
-                          ZLIB_INCLUDE=" -I$ZLIB_ROOT/include"
-                          ZLIB_LIBS=" -L$ZLIB_ROOT/lib -lz" ;; #(
-  *) :
-     ;;
-esac
-else
-  for ac_header in zlib.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_zlib_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_ZLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-                      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
-$as_echo_n "checking for library containing deflate... " >&6; }
-if ${ac_cv_search_deflate+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' z; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_deflate=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_deflate+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_deflate+:} false; then :
-
-else
-  ac_cv_search_deflate=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
-$as_echo "$ac_cv_search_deflate" >&6; }
-ac_res=$ac_cv_search_deflate
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
-
-fi
-
-              ZLIB_LIBS=" -lz"
-fi
-
-
-
-#  ----------------------------------------------------------------------
-#  Compile application with SZLIB library, needed for GRIB1 or for
-#  linking against hdf5/netcdf4
+#  Compile application with SZLIB library, needed for GRIB1 linking
 SZLIB_INCLUDE=''
 SZLIB_LIBS=''
 
@@ -18830,7 +18582,7 @@ if test "$ac_res" != no; then :
 $as_echo "#define HAVE_LIBHDF5 1" >>confdefs.h
 
 else
-  as_fn_error $? "Cannot link to hdf5 library! It is required for Netcdf4" "$LINENO" 5
+  as_fn_error $? "Cannot link to hdf5 library!" "$LINENO" 5
 fi
 
                             { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5DSis_scale" >&5
@@ -18888,8 +18640,8 @@ if test "$ac_res" != no; then :
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
   have_hdf5_hl=yes
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot find hdf5 high level interface! It is required for netCDF4." >&5
-$as_echo "$as_me: Cannot find hdf5 high level interface! It is required for netCDF4." >&6;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot find hdf5 high level interface!" >&5
+$as_echo "$as_me: Cannot find hdf5 high level interface!" >&6;}
                                             have_hdf5_hl=no
 fi
 
@@ -18973,7 +18725,7 @@ if test "$ac_res" != no; then :
 $as_echo "#define HAVE_LIBHDF5 1" >>confdefs.h
 
 else
-  as_fn_error $? "Cannot link to hdf5! It is required for netCDF4." "$LINENO" 5
+  as_fn_error $? "Cannot link to hdf5!" "$LINENO" 5
 fi
 
                                  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5DSis_scale" >&5
@@ -19031,14 +18783,8 @@ if test "$ac_res" != no; then :
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
   have_hdf5_hl=yes
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot link to hdf5 high level interface! It is required for netCDF4.\
-                                                                HDF5 must be built with zlib; the location of zlib must be specified for HDF5 with the \
-                                                                --with-zlib option. If HDF5 was also built with szlib, then the location of szlib must also be \
-                                                                specified with the --with-szlib option.." >&5
-$as_echo "$as_me: Cannot link to hdf5 high level interface! It is required for netCDF4.\
-                                                                HDF5 must be built with zlib; the location of zlib must be specified for HDF5 with the \
-                                                                --with-zlib option. If HDF5 was also built with szlib, then the location of szlib must also be \
-                                                                specified with the --with-szlib option.." >&6;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot link to hdf5 high level interface!" >&5
+$as_echo "$as_me: Cannot link to hdf5 high level interface!" >&6;}
                                                 have_hdf5_hl=no
 fi
 
@@ -19079,8 +18825,8 @@ ENABLE_NC4HDF5=no
 if test "${with_netcdf+set}" = set; then :
   withval=$with_netcdf; case "$with_netcdf" in #(
   no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for netCDF library" >&5
-$as_echo_n "checking for netCDF library... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NetCDF library" >&5
+$as_echo_n "checking for NetCDF library... " >&6; }
                            { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
 $as_echo "suppressed" >&6; } ;; #(
   yes) :
@@ -19154,11 +18900,10 @@ $as_echo "#define HAVE_LIBNETCDF 1" >>confdefs.h
 
                                             ENABLE_NETCDF=yes
 else
-  as_fn_error $? "Could not link to netCDF library" "$LINENO" 5
+  as_fn_error $? "Could not link to NetCDF library" "$LINENO" 5
 fi
 
                             NETCDF_LIBS=" -lnetcdf"
-
                             # Extract the first word of "nc-config", so it can be a program name with args.
 set dummy nc-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -19314,12 +19059,11 @@ $as_echo "#define HAVE_LIBNETCDF 1" >>confdefs.h
 
                                                  ENABLE_NETCDF=yes
 else
-  as_fn_error $? "Could not link to netcdf library" "$LINENO" 5
+  as_fn_error $? "Could not link to NetCDF library" "$LINENO" 5
 fi
 
                                  NETCDF_LIBS=" -L$NETCDF_ROOT/lib -lnetcdf"
                                  NETCDF_INCLUDE=" -I$NETCDF_ROOT/include"
-
                                  { $as_echo "$as_me:${as_lineno-$LINENO}: checking nc-config script" >&5
 $as_echo_n "checking nc-config script... " >&6; }
                                  # Extract the first word of "nc-config", so it can be a program name with args.
@@ -19416,15 +19160,15 @@ else
 $as_echo "Could not find nc-config! go on with default configuration" >&6; }
 fi
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: $with_netcdf is not a directory! NETCDF suppressed" >&5
-$as_echo "$as_me: $with_netcdf is not a directory! NETCDF suppressed" >&6;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: $with_netcdf is not a directory! NetCDF suppressed" >&5
+$as_echo "$as_me: $with_netcdf is not a directory! NetCDF suppressed" >&6;}
 fi ;; #(
   *) :
      ;;
 esac
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NETCDF library" >&5
-$as_echo_n "checking for NETCDF library... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NetCDF library" >&5
+$as_echo_n "checking for NetCDF library... " >&6; }
              { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
 $as_echo "suppressed" >&6; }
 fi
@@ -19499,33 +19243,32 @@ fi
 
 
 #  ----------------------------------------------------------------------
-#  Link application with CMOR library
-CMOR_LIBS=''
+#  Link application with UDUNITS2 library
 
-# Check whether --with-cmor was given.
-if test "${with_cmor+set}" = set; then :
-  withval=$with_cmor; case "$with_cmor" in #(
+# Check whether --with-udunits2 was given.
+if test "${with_udunits2+set}" = set; then :
+  withval=$with_udunits2; case "$with_udunits2" in #(
   no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cmor library" >&5
-$as_echo_n "checking for cmor library... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for udunits2 library" >&5
+$as_echo_n "checking for udunits2 library... " >&6; }
                            { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
 $as_echo "suppressed" >&6; } ;; #(
   yes) :
-    for ac_header in cmor.h
+    for ac_header in udunits2.h
 do :
-  ac_fn_c_check_header_mongrel "$LINENO" "cmor.h" "ac_cv_header_cmor_h" "$ac_includes_default"
-if test "x$ac_cv_header_cmor_h" = xyes; then :
+  ac_fn_c_check_header_mongrel "$LINENO" "udunits2.h" "ac_cv_header_udunits2_h" "$ac_includes_default"
+if test "x$ac_cv_header_udunits2_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_CMOR_H 1
+#define HAVE_UDUNITS2_H 1
 _ACEOF
 
 fi
 
 done
 
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cmor_load_table" >&5
-$as_echo_n "checking for library containing cmor_load_table... " >&6; }
-if ${ac_cv_search_cmor_load_table+:} false; then :
+                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ut_parse" >&5
+$as_echo_n "checking for library containing ut_parse... " >&6; }
+if ${ac_cv_search_ut_parse+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
@@ -19538,16 +19281,16 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char cmor_load_table ();
+char ut_parse ();
 int
 main ()
 {
-return cmor_load_table ();
+return ut_parse ();
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' cmor; do
+for ac_lib in '' udunits2; do
   if test -z "$ac_lib"; then
     ac_res="none required"
   else
@@ -19555,56 +19298,251 @@ for ac_lib in '' cmor; do
     LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
   fi
   if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_cmor_load_table=$ac_res
+  ac_cv_search_ut_parse=$ac_res
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext
-  if ${ac_cv_search_cmor_load_table+:} false; then :
+  if ${ac_cv_search_ut_parse+:} false; then :
   break
 fi
 done
-if ${ac_cv_search_cmor_load_table+:} false; then :
+if ${ac_cv_search_ut_parse+:} false; then :
 
 else
-  ac_cv_search_cmor_load_table=no
+  ac_cv_search_ut_parse=no
 fi
 rm conftest.$ac_ext
 LIBS=$ac_func_search_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cmor_load_table" >&5
-$as_echo "$ac_cv_search_cmor_load_table" >&6; }
-ac_res=$ac_cv_search_cmor_load_table
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ut_parse" >&5
+$as_echo "$ac_cv_search_ut_parse" >&6; }
+ac_res=$ac_cv_search_ut_parse
 if test "$ac_res" != no; then :
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
-$as_echo "#define HAVE_LIBCMOR 1" >>confdefs.h
+$as_echo "#define HAVE_LIBUDUNITS2 1" >>confdefs.h
 
 else
-  as_fn_error $? "Could not link to cmor library!" "$LINENO" 5
+  as_fn_error $? "Could not link to udunits2 library!" "$LINENO" 5
 fi
 
-                            CMOR_LIBS=" -lcmor"
+                            UDUNITS_LDFLAGS=" -ludunits2"
+
+                            UDUNITS_INCLUDE=""
  ;; #(
   *) :
-    CMOR_ROOT=$with_cmor
-                          if test -d "$CMOR_ROOT"; then :
-  LDFLAGS="$LDFLAGS -L$CMOR_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$CMOR_ROOT/include"
-                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cmor_load_table" >&5
-$as_echo_n "checking for library containing cmor_load_table... " >&6; }
-if ${ac_cv_search_cmor_load_table+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
+    UDUNITS_ROOT=$with_udunits2
+                          if test -d "$UDUNITS_ROOT"; then :
+  LDFLAGS="$LDFLAGS -L$UDUNITS_ROOT/lib"
+                                 CPPFLAGS="$CPPFLAGS -I$UDUNITS_ROOT/include -I$UDUNITS_ROOT/include/udunits2"
+                                 for ac_header in udunits2.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "udunits2.h" "ac_cv_header_udunits2_h" "$ac_includes_default"
+if test "x$ac_cv_header_udunits2_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_UDUNITS2_H 1
+_ACEOF
+
+fi
+
+done
+
+                                 for ac_header in udunits2/udunits2.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "udunits2/udunits2.h" "ac_cv_header_udunits2_udunits2_h" "$ac_includes_default"
+if test "x$ac_cv_header_udunits2_udunits2_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_UDUNITS2_UDUNITS2_H 1
+_ACEOF
+
+fi
+
+done
+
+                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ut_parse" >&5
+$as_echo_n "checking for library containing ut_parse... " >&6; }
+if ${ac_cv_search_ut_parse+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ut_parse ();
+int
+main ()
+{
+return ut_parse ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' udunits2; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_ut_parse=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_ut_parse+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_ut_parse+:} false; then :
+
+else
+  ac_cv_search_ut_parse=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ut_parse" >&5
+$as_echo "$ac_cv_search_ut_parse" >&6; }
+ac_res=$ac_cv_search_ut_parse
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_LIBUDUNITS2 1" >>confdefs.h
+
+else
+  as_fn_error $? "Could not link to udunits2 library!" "$LINENO" 5
+fi
+
+                                 UDUNITS_LDFLAGS=" -L$UDUNITS_ROOT/lib -ludunits2"
+
+                                 UDUNITS_INCLUDE=" -I$UDUNITS_ROOT/include"
+
+else
+  as_fn_error $? "$UDUNITS_ROOT is not a directory! UDUNITS2 suppressed" "$LINENO" 5
+fi ;; #(
+  *) :
+     ;;
+esac
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the UDUNITS2 library" >&5
+$as_echo_n "checking for the UDUNITS2 library... " >&6; }
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
+$as_echo "suppressed" >&6; }
+fi
+
+#  ----------------------------------------------------------------------
+#  Link application with CMOR library
+CMOR_LIBS=''
+
+# Check whether --with-cmor was given.
+if test "${with_cmor+set}" = set; then :
+  withval=$with_cmor; case "$with_cmor" in #(
+  no) :
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cmor library" >&5
+$as_echo_n "checking for cmor library... " >&6; }
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
+$as_echo "suppressed" >&6; } ;; #(
+  yes) :
+    for ac_header in cmor.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "cmor.h" "ac_cv_header_cmor_h" "$ac_includes_default"
+if test "x$ac_cv_header_cmor_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CMOR_H 1
+_ACEOF
+
+fi
+
+done
+
+                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cmor_load_table" >&5
+$as_echo_n "checking for library containing cmor_load_table... " >&6; }
+if ${ac_cv_search_cmor_load_table+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char cmor_load_table ();
+int
+main ()
+{
+return cmor_load_table ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' cmor; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_cmor_load_table=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_cmor_load_table+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_cmor_load_table+:} false; then :
+
+else
+  ac_cv_search_cmor_load_table=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cmor_load_table" >&5
+$as_echo "$ac_cv_search_cmor_load_table" >&6; }
+ac_res=$ac_cv_search_cmor_load_table
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_LIBCMOR 1" >>confdefs.h
+
+else
+  as_fn_error $? "Could not link to cmor library!" "$LINENO" 5
+fi
+
+                            CMOR_LIBS=" -lcmor"
+ ;; #(
+  *) :
+    CMOR_ROOT=$with_cmor
+                          if test -d "$CMOR_ROOT"; then :
+  LDFLAGS="$LDFLAGS -L$CMOR_ROOT/lib"
+                                 CPPFLAGS="$CPPFLAGS -I$CMOR_ROOT/include -I$CMOR_ROOT/include/cdTime"
+                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cmor_load_table" >&5
+$as_echo_n "checking for library containing cmor_load_table... " >&6; }
+if ${ac_cv_search_cmor_load_table+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
 char cmor_load_table ();
 int
 main ()
@@ -20418,200 +20356,6 @@ $as_echo "suppressed" >&6; }
 fi
 
 #  ----------------------------------------------------------------------
-#  Link application with UDUNITS2 library
-
-# Check whether --with-udunits2 was given.
-if test "${with_udunits2+set}" = set; then :
-  withval=$with_udunits2; case "$with_udunits2" in #(
-  no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for udunits2 library" >&5
-$as_echo_n "checking for udunits2 library... " >&6; }
-                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; } ;; #(
-  yes) :
-    for ac_header in udunits2.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "udunits2.h" "ac_cv_header_udunits2_h" "$ac_includes_default"
-if test "x$ac_cv_header_udunits2_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_UDUNITS2_H 1
-_ACEOF
-
-fi
-
-done
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ut_parse" >&5
-$as_echo_n "checking for library containing ut_parse... " >&6; }
-if ${ac_cv_search_ut_parse+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ut_parse ();
-int
-main ()
-{
-return ut_parse ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' udunits2; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_ut_parse=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_ut_parse+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_ut_parse+:} false; then :
-
-else
-  ac_cv_search_ut_parse=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ut_parse" >&5
-$as_echo "$ac_cv_search_ut_parse" >&6; }
-ac_res=$ac_cv_search_ut_parse
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBUDUNITS2 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to udunits2 library!" "$LINENO" 5
-fi
-
-                            UDUNITS_LDFLAGS=" -ludunits2"
-
-                            UDUNITS_INCLUDE=""
- ;; #(
-  *) :
-    UDUNITS_ROOT=$with_udunits2
-                          if test -d "$UDUNITS_ROOT"; then :
-  LDFLAGS="$LDFLAGS -L$UDUNITS_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$UDUNITS_ROOT/include"
-                                 for ac_header in udunits2.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "udunits2.h" "ac_cv_header_udunits2_h" "$ac_includes_default"
-if test "x$ac_cv_header_udunits2_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_UDUNITS2_H 1
-_ACEOF
-
-fi
-
-done
-
-                                 for ac_header in udunits2/udunits2.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "udunits2/udunits2.h" "ac_cv_header_udunits2_udunits2_h" "$ac_includes_default"
-if test "x$ac_cv_header_udunits2_udunits2_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_UDUNITS2_UDUNITS2_H 1
-_ACEOF
-
-fi
-
-done
-
-                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ut_parse" >&5
-$as_echo_n "checking for library containing ut_parse... " >&6; }
-if ${ac_cv_search_ut_parse+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ut_parse ();
-int
-main ()
-{
-return ut_parse ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' udunits2; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_ut_parse=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_ut_parse+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_ut_parse+:} false; then :
-
-else
-  ac_cv_search_ut_parse=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ut_parse" >&5
-$as_echo "$ac_cv_search_ut_parse" >&6; }
-ac_res=$ac_cv_search_ut_parse
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBUDUNITS2 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to udunits2 library!" "$LINENO" 5
-fi
-
-                                 UDUNITS_LDFLAGS=" -L$UDUNITS_ROOT/lib -ludunits2"
-
-                                 UDUNITS_INCLUDE=" -I$UDUNITS_ROOT/include"
-
-else
-  as_fn_error $? "$UDUNITS_ROOT is not a directory! UDUNITS2 suppressed" "$LINENO" 5
-fi ;; #(
-  *) :
-     ;;
-esac
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the UDUNITS2 library" >&5
-$as_echo_n "checking for the UDUNITS2 library... " >&6; }
-             { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; }
-fi
-
-#  ----------------------------------------------------------------------
 #  Compile application with MAGICS (xml required)
 MAGICS_ROOT=''
 MAGICS_INCLUDE=''
@@ -21318,9 +21062,11 @@ ac_config_files="$ac_config_files test/Select.test test/Spectral.test test/Timst
 
 ac_config_files="$ac_config_files test/Ymonstat.test test/Fldstat.test test/Fldpctl.test test/Ensstat.test test/Enspctl.test"
 
-ac_config_files="$ac_config_files test/Afterburner.test test/Detrend.test test/Arith.test test/Expr.test"
+ac_config_files="$ac_config_files test/Afterburner.test test/Detrend.test test/Arithc.test test/Arith.test test/Expr.test"
+
+ac_config_files="$ac_config_files test/Gradsdes.test test/Collgrid.test test/threads.test test/tsformat.test test/wildcard.test"
 
-ac_config_files="$ac_config_files test/Gradsdes.test test/Collgrid.test test/threads.test test/wildcard.test"
+ac_config_files="$ac_config_files test/MapReduce.test test/Ninfo.test"
 
 ac_config_files="$ac_config_files Makefile src/Makefile contrib/Makefile test/Makefile test/data/Makefile cdo.spec cdo.settings"
 
@@ -21898,7 +21644,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.7.1, which was
+This file was extended by cdo $as_me 1.7.2, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21964,7 +21710,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.7.1
+cdo config.status 1.7.2
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
@@ -22490,12 +22236,16 @@ do
     "test/Enspctl.test") CONFIG_FILES="$CONFIG_FILES test/Enspctl.test" ;;
     "test/Afterburner.test") CONFIG_FILES="$CONFIG_FILES test/Afterburner.test" ;;
     "test/Detrend.test") CONFIG_FILES="$CONFIG_FILES test/Detrend.test" ;;
+    "test/Arithc.test") CONFIG_FILES="$CONFIG_FILES test/Arithc.test" ;;
     "test/Arith.test") CONFIG_FILES="$CONFIG_FILES test/Arith.test" ;;
     "test/Expr.test") CONFIG_FILES="$CONFIG_FILES test/Expr.test" ;;
     "test/Gradsdes.test") CONFIG_FILES="$CONFIG_FILES test/Gradsdes.test" ;;
     "test/Collgrid.test") CONFIG_FILES="$CONFIG_FILES test/Collgrid.test" ;;
     "test/threads.test") CONFIG_FILES="$CONFIG_FILES test/threads.test" ;;
+    "test/tsformat.test") CONFIG_FILES="$CONFIG_FILES test/tsformat.test" ;;
     "test/wildcard.test") CONFIG_FILES="$CONFIG_FILES test/wildcard.test" ;;
+    "test/MapReduce.test") CONFIG_FILES="$CONFIG_FILES test/MapReduce.test" ;;
+    "test/Ninfo.test") CONFIG_FILES="$CONFIG_FILES test/Ninfo.test" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
     "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;;
@@ -24007,12 +23757,16 @@ _LT_EOF
     "test/Enspctl.test":F) chmod a+x "$ac_file" ;;
     "test/Afterburner.test":F) chmod a+x "$ac_file" ;;
     "test/Detrend.test":F) chmod a+x "$ac_file" ;;
+    "test/Arithc.test":F) chmod a+x "$ac_file" ;;
     "test/Arith.test":F) chmod a+x "$ac_file" ;;
     "test/Expr.test":F) chmod a+x "$ac_file" ;;
     "test/Gradsdes.test":F) chmod a+x "$ac_file" ;;
     "test/Collgrid.test":F) chmod a+x "$ac_file" ;;
     "test/threads.test":F) chmod a+x "$ac_file" ;;
+    "test/tsformat.test":F) chmod a+x "$ac_file" ;;
     "test/wildcard.test":F) chmod a+x "$ac_file" ;;
+    "test/MapReduce.test":F) chmod a+x "$ac_file" ;;
+    "test/Ninfo.test":F) chmod a+x "$ac_file" ;;
 
   esac
 done # for ac_tag
diff --git a/configure.ac b/configure.ac
index 518d115..0c0ff2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 #  autoconf 2.68
 #  libtool  2.4.2
 
-AC_INIT([cdo], [1.7.1], [http://mpimet.mpg.de/cdo])
+AC_INIT([cdo], [1.7.2], [http://mpimet.mpg.de/cdo])
 
 AC_DEFINE_UNQUOTED(CDO, ["$PACKAGE_VERSION"], [CDO version])
 
@@ -251,8 +251,9 @@ AC_CONFIG_FILES([test/File.test test/Read_grib.test test/Read_netcdf.test test/C
 AC_CONFIG_FILES([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/Ymonstat.test test/Fldstat.test test/Fldpctl.test test/Ensstat.test test/Enspctl.test],[chmod a+x "$ac_file"])
-AC_CONFIG_FILES([test/Afterburner.test test/Detrend.test test/Arith.test test/Expr.test],[chmod a+x "$ac_file"])
-AC_CONFIG_FILES([test/Gradsdes.test test/Collgrid.test test/threads.test test/wildcard.test],[chmod a+x "$ac_file"])
+AC_CONFIG_FILES([test/Afterburner.test test/Detrend.test test/Arithc.test test/Arith.test test/Expr.test],[chmod a+x "$ac_file"])
+AC_CONFIG_FILES([test/Gradsdes.test test/Collgrid.test test/threads.test test/tsformat.test test/wildcard.test],[chmod a+x "$ac_file"])
+AC_CONFIG_FILES([test/MapReduce.test test/Ninfo.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([Makefile src/Makefile contrib/Makefile test/Makefile test/data/Makefile cdo.spec cdo.settings])
 AC_OUTPUT
 
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index bd25d2a..8f61d60 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -1,21 +1,23 @@
 EXTRA_DIST = makecompl.rb cdoCompletion.bash cdoCompletion.tcsh cdoCompletion.zsh
-CLEANFILES = 
+CLEANFILES =
 
 completions:
-	if (hash ruby &> /dev/null) ; then \
+	if hash ruby >/dev/null 2>&1 ; then \
 	  ruby -KN $(srcdir)/makecompl.rb -o cdoCompletion; \
 	fi
 
+cdoCompletion.bash cdoCompletion.zsh cdoCompletion.tcsh: completions
+
 test:
-	if (hash ruby &> /dev/null) ; then \
-	    (cd ruby;ruby test/test_cdo.rb) \
+	if hash ruby >/dev/null 2>&1 ; then \
+	    cd ruby;ruby test/test_cdo.rb \
 	fi
-	if (hash python &> /dev/null) ; then \
-	    (cd python; python test/test_cdo.py) \
+	if hash python >/dev/null 2>&1 ; then \
+	    cd python; python test/test_cdo.py \
 	fi
 
-if MAINTAINER_MODE
+#if MAINTAINER_MODE
 all-local: completions
 
-CLEANFILES  += `ls cdoCompletion.*`
-endif
+CLEANFILES += `ls cdoCompletion.*`
+#endif
diff --git a/contrib/Makefile.in b/contrib/Makefile.in
index e3ff687..652f7d3 100644
--- a/contrib/Makefile.in
+++ b/contrib/Makefile.in
@@ -77,7 +77,6 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at MAINTAINER_MODE_TRUE@am__append_1 = `ls cdoCompletion.*`
 subdir = contrib
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/config/mkinstalldirs COPYING
@@ -231,8 +230,6 @@ UDUNITS_LDFLAGS = @UDUNITS_LDFLAGS@
 USER_NAME = @USER_NAME@
 VERSION = @VERSION@
 XML2_LIBS = @XML2_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -289,7 +286,7 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 EXTRA_DIST = makecompl.rb cdoCompletion.bash cdoCompletion.tcsh cdoCompletion.zsh
-CLEANFILES = $(am__append_1)
+CLEANFILES = `ls cdoCompletion.*`
 all: all-am
 
 .SUFFIXES:
@@ -368,7 +365,6 @@ distdir: $(DISTFILES)
 	done
 check-am: all-am
 check: check-am
- at MAINTAINER_MODE_FALSE@all-local:
 all-am: Makefile all-local
 installdirs:
 install: install-am
@@ -485,19 +481,23 @@ uninstall-am:
 
 
 completions:
-	if (hash ruby &> /dev/null) ; then \
+	if hash ruby >/dev/null 2>&1 ; then \
 	  ruby -KN $(srcdir)/makecompl.rb -o cdoCompletion; \
 	fi
 
+cdoCompletion.bash cdoCompletion.zsh cdoCompletion.tcsh: completions
+
 test:
-	if (hash ruby &> /dev/null) ; then \
-	    (cd ruby;ruby test/test_cdo.rb) \
+	if hash ruby >/dev/null 2>&1 ; then \
+	    cd ruby;ruby test/test_cdo.rb \
 	fi
-	if (hash python &> /dev/null) ; then \
-	    (cd python; python test/test_cdo.py) \
+	if hash python >/dev/null 2>&1 ; then \
+	    cd python; python test/test_cdo.py \
 	fi
 
- at MAINTAINER_MODE_TRUE@all-local: completions
+#if MAINTAINER_MODE
+all-local: completions
+#endif
 
 # 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/contrib/cdoCompletion.bash b/contrib/cdoCompletion.bash
index 517486b..b6b8203 100644
--- a/contrib/cdoCompletion.bash
+++ b/contrib/cdoCompletion.bash
@@ -1,39 +1,778 @@
 complete -W "
--- \
--- \
--- \
--- \
--- \
--- \
--- \
+--cmor \
+--enableexcept \
+--history \
+--netcdf_hdr_pad, \
+--no_warnings \
+--operators \
+--percentile \
+--reduce_dim \
+--sort \
+--timestat_date \
+-C, \
 -L \
 -M \
 -O \
 -P \
--Q \
--R \
+-R, \
 -S \
--V \
+-V, \
 -W \
 -a \
 -b \
--f \
+-f, \
 -g \
--h \
+-h, \
 -k \
 -m \
 -r \
--s \
+-s, \
 -t \
--v \
+-v, \
 -z \
---operators ---operators \
-Use -Use \
-a -a \
-all -all \
+abs -abs \
+acos -acos \
+add -add \
+addc -addc \
+adipot -adipot \
+adisit -adisit \
+aexpr -aexpr \
+aexprf -aexprf \
+after -after \
+afterburner -afterburner \
+anomaly -anomaly \
+ap2hl -ap2hl \
+ap2hlx -ap2hlx \
+ap2pl -ap2pl \
+ap2pl_lp -ap2pl_lp \
+ap2plx -ap2plx \
+ap2plx_lp -ap2plx_lp \
+asin -asin \
+atan -atan \
+atan2 -atan2 \
+bandpass -bandpass \
+boxavg -boxavg \
+cat -cat \
+cdiread -cdiread \
+cdiwrite -cdiwrite \
+chcode -chcode \
+chlevel -chlevel \
+chlevelc -chlevelc \
+chlevelv -chlevelv \
+chltype -chltype \
+chname -chname \
+chparam -chparam \
+chtabnum -chtabnum \
+chunit -chunit \
+chvar -chvar \
+cloudlayer -cloudlayer \
+cmor -cmor \
+codetab -codetab \
+collgrid -collgrid \
+complextorect -complextorect \
+consecsum -consecsum \
+consects -consects \
+const -const \
+contour -contour \
+conv_cmor_table -conv_cmor_table \
+copy -copy \
+cos -cos \
+coshill -coshill \
+covar0 -covar0 \
+covar0r -covar0r \
+dayavg -dayavg \
+daycount -daycount \
+daymax -daymax \
+daymean -daymean \
+daymin -daymin \
+daypctl -daypctl \
+daystd -daystd \
+daystd1 -daystd1 \
+daysum -daysum \
+dayvar -dayvar \
+dayvar1 -dayvar1 \
+del29feb -del29feb \
+delcode -delcode \
+delday -delday \
+delete -delete \
+delname -delname \
+delparam -delparam \
+deltap -deltap \
+deltap_fl -deltap_fl \
+delvar -delvar \
+detrend -detrend \
+diff -diff \
+diffc -diffc \
+diffn -diffn \
+diffp -diffp \
+diffv -diffv \
+distgrid -distgrid \
+div -div \
+divc -divc \
+divcoslat -divcoslat \
+divdpm -divdpm \
+divdpy -divdpy \
+dumpmap -dumpmap \
+duplicate -duplicate \
+dv2ps -dv2ps \
+dv2uv -dv2uv \
+dv2uvl -dv2uvl \
+eca_cdd -eca_cdd \
+eca_cfd -eca_cfd \
+eca_csu -eca_csu \
+eca_cwd -eca_cwd \
+eca_cwdi -eca_cwdi \
+eca_cwfi -eca_cwfi \
+eca_etr -eca_etr \
+eca_fd -eca_fd \
+eca_gsl -eca_gsl \
+eca_hd -eca_hd \
+eca_hwdi -eca_hwdi \
+eca_hwfi -eca_hwfi \
+eca_id -eca_id \
+eca_pd -eca_pd \
+eca_r10mm -eca_r10mm \
+eca_r1mm -eca_r1mm \
+eca_r20mm -eca_r20mm \
+eca_r75p -eca_r75p \
+eca_r75ptot -eca_r75ptot \
+eca_r90p -eca_r90p \
+eca_r90ptot -eca_r90ptot \
+eca_r95p -eca_r95p \
+eca_r95ptot -eca_r95ptot \
+eca_r99p -eca_r99p \
+eca_r99ptot -eca_r99ptot \
+eca_rr1 -eca_rr1 \
+eca_rx1day -eca_rx1day \
+eca_rx5day -eca_rx5day \
+eca_sdii -eca_sdii \
+eca_su -eca_su \
+eca_tg10p -eca_tg10p \
+eca_tg90p -eca_tg90p \
+eca_tn10p -eca_tn10p \
+eca_tn90p -eca_tn90p \
+eca_tr -eca_tr \
+eca_tx10p -eca_tx10p \
+eca_tx90p -eca_tx90p \
+enlarge -enlarge \
+ensavg -ensavg \
+ensbrs -ensbrs \
+enscrps -enscrps \
+ensmax -ensmax \
+ensmean -ensmean \
+ensmin -ensmin \
+enspctl -enspctl \
+ensrkhist_space -ensrkhist_space \
+ensrkhist_time -ensrkhist_time \
+ensrkhistspace -ensrkhistspace \
+ensrkhisttime -ensrkhisttime \
+ensroc -ensroc \
+ensstd -ensstd \
+ensstd1 -ensstd1 \
+enssum -enssum \
+ensvar -ensvar \
+ensvar1 -ensvar1 \
+eof -eof \
+eof3d -eof3d \
+eof3dspatial -eof3dspatial \
+eof3dtime -eof3dtime \
+eofcoeff -eofcoeff \
+eofcoeff3d -eofcoeff3d \
+eofspatial -eofspatial \
+eoftime -eoftime \
+eq -eq \
+eqc -eqc \
+exp -exp \
+export_e5ml -export_e5ml \
+export_e5res -export_e5res \
+expr -expr \
+exprf -exprf \
+fc2gp -fc2gp \
+fc2sp -fc2sp \
+fdns -fdns \
+filedes -filedes \
+fillmiss -fillmiss \
+fillmiss2 -fillmiss2 \
+fldavg -fldavg \
+fldcor -fldcor \
+fldcovar -fldcovar \
+fldmax -fldmax \
+fldmean -fldmean \
+fldmin -fldmin \
+fldpctl -fldpctl \
+fldrms -fldrms \
+fldstd -fldstd \
+fldstd1 -fldstd1 \
+fldsum -fldsum \
+fldvar -fldvar \
+fldvar1 -fldvar1 \
 for -for \
-list -list \
-of -of \
-operators. -operators. \
-option -option \
+fourier -fourier \
+fpressure -fpressure \
+gather -gather \
+ge -ge \
+gec -gec \
+genbic -genbic \
+genbil -genbil \
+gencon -gencon \
+gencon2 -gencon2 \
+gendis -gendis \
+gengrid -gengrid \
+genlaf -genlaf \
+genlevelbounds -genlevelbounds \
+gennn -gennn \
+genycon -genycon \
+geopotheight -geopotheight \
+ggstat -ggstat \
+ggstats -ggstats \
+gheight -gheight \
+globavg -globavg \
+gmtcells -gmtcells \
+gmtxyz -gmtxyz \
+gp2fc -gp2fc \
+gp2sp -gp2sp \
+gp2spl -gp2spl \
+gradsdes -gradsdes \
+graph -graph \
+grfill -grfill \
+gridarea -gridarea \
+gridboxavg -gridboxavg \
+gridboxmax -gridboxmax \
+gridboxmean -gridboxmean \
+gridboxmin -gridboxmin \
+gridboxstd -gridboxstd \
+gridboxstd1 -gridboxstd1 \
+gridboxsum -gridboxsum \
+gridboxvar -gridboxvar \
+gridboxvar1 -gridboxvar1 \
+griddes -griddes \
+griddes2 -griddes2 \
+griddx -griddx \
+griddy -griddy \
+gridmask -gridmask \
+gridverify -gridverify \
+gridweights -gridweights \
+gt -gt \
+gtc -gtc \
+harmonic -harmonic \
+highpass -highpass \
+histcount -histcount \
+histfreq -histfreq \
+histmean -histmean \
+histsum -histsum \
+houravg -houravg \
+hourcount -hourcount \
+hourmax -hourmax \
+hourmean -hourmean \
+hourmin -hourmin \
+hourpctl -hourpctl \
+hourstd -hourstd \
+hourstd1 -hourstd1 \
+hoursum -hoursum \
+hourvar -hourvar \
+hourvar1 -hourvar1 \
+hpressure -hpressure \
+hurr -hurr \
+ifnotthen -ifnotthen \
+ifnotthenc -ifnotthenc \
+ifthen -ifthen \
+ifthenc -ifthenc \
+ifthenelse -ifthenelse \
+import_amsr -import_amsr \
+import_binary -import_binary \
+import_cmsaf -import_cmsaf \
+import_e5ml -import_e5ml \
+import_e5res -import_e5res \
+import_grads -import_grads \
+import_obs -import_obs \
+imtocomplex -imtocomplex \
+info -info \
+infoc -infoc \
+infon -infon \
+infop -infop \
+infos -infos \
+infov -infov \
+input -input \
+inputext -inputext \
+inputsrv -inputsrv \
+int -int \
+interpolate -interpolate \
+intgrid -intgrid \
+intgridbil -intgridbil \
+intgridcon -intgridcon \
+intgridtraj -intgridtraj \
+intlevel -intlevel \
+intlevel3d -intlevel3d \
+intlevelx -intlevelx \
+intlevelx3d -intlevelx3d \
+intntime -intntime \
+intpoint -intpoint \
+inttime -inttime \
+intyear -intyear \
+invertlat -invertlat \
+invertlatdata -invertlatdata \
+invertlatdes -invertlatdes \
+invertlev -invertlev \
+invertlon -invertlon \
+invertlondata -invertlondata \
+invertlondes -invertlondes \
+isosurface -isosurface \
+le -le \
+lec -lec \
+lmavg -lmavg \
+lmean -lmean \
+lmmean -lmmean \
+lmstd -lmstd \
+ln -ln \
+log -log \
+log10 -log10 \
+lowpass -lowpass \
+lsmean -lsmean \
+lt -lt \
+ltc -ltc \
+map -map \
+mask -mask \
+maskindexbox -maskindexbox \
+masklonlatbox -masklonlatbox \
+maskregion -maskregion \
+mastrfu -mastrfu \
+max -max \
+meandiff2test -meandiff2test \
+meravg -meravg \
+merge -merge \
+mergegrid -mergegrid \
+mergetime -mergetime \
+mermax -mermax \
+mermean -mermean \
+mermin -mermin \
+merpctl -merpctl \
+merstd -merstd \
+merstd1 -merstd1 \
+mersum -mersum \
+mervar -mervar \
+mervar1 -mervar1 \
+min -min \
+ml2hl -ml2hl \
+ml2hl_lp -ml2hl_lp \
+ml2hlx -ml2hlx \
+ml2hlx_lp -ml2hlx_lp \
+ml2pl -ml2pl \
+ml2pl_lp -ml2pl_lp \
+ml2plx -ml2plx \
+ml2plx_lp -ml2plx_lp \
+mod -mod \
+monadd -monadd \
+monavg -monavg \
+moncount -moncount \
+mondiv -mondiv \
+monmax -monmax \
+monmean -monmean \
+monmin -monmin \
+monmul -monmul \
+monpctl -monpctl \
+monstd -monstd \
+monstd1 -monstd1 \
+monsub -monsub \
+monsum -monsum \
+monvar -monvar \
+monvar1 -monvar1 \
+mrotuv -mrotuv \
+mrotuvb -mrotuvb \
+mul -mul \
+mulc -mulc \
+mulcoslat -mulcoslat \
+muldoy -muldoy \
+muldpm -muldpm \
+muldpy -muldpy \
+ncode -ncode \
+ncode -ncode \
+ncopy -ncopy \
+ndate -ndate \
+ne -ne \
+nec -nec \
+ngridpoints -ngridpoints \
+ngrids -ngrids \
+nint -nint \
+nlevel -nlevel \
+nmon -nmon \
+npar -npar \
+ntime -ntime \
+nvar -nvar \
+nyear -nyear \
+output -output \
+outputarr -outputarr \
+outputbounds -outputbounds \
+outputboundscpt -outputboundscpt \
+outputcenter -outputcenter \
+outputcenter2 -outputcenter2 \
+outputcentercpt -outputcentercpt \
+outputext -outputext \
+outputf -outputf \
+outputfld -outputfld \
+outputint -outputint \
+outputkey -outputkey \
+outputsrv -outputsrv \
+outputtab -outputtab \
+outputtri -outputtri \
+outputts -outputts \
+outputvector -outputvector \
+outputvrml -outputvrml \
+outputxyz -outputxyz \
+pack -pack \
+pardes -pardes \
+pardup -pardup \
+parmul -parmul \
+partab -partab \
+partab2 -partab2 \
+pinfo -pinfo \
+pinfov -pinfov \
+pow -pow \
+pressure_fl -pressure_fl \
+pressure_hl -pressure_hl \
+random -random \
+read_cmor_table -read_cmor_table \
+reci -reci \
+reducegrid -reducegrid \
+regres -regres \
+remap -remap \
+remapbic -remapbic \
+remapbil -remapbil \
+remapcon -remapcon \
+remapcon1 -remapcon1 \
+remapcon2 -remapcon2 \
+remapdis -remapdis \
+remapdis1 -remapdis1 \
+remapeta -remapeta \
+remapeta_s -remapeta_s \
+remapeta_z -remapeta_z \
+remaplaf -remaplaf \
+remapnn -remapnn \
+remapsum -remapsum \
+remapycon -remapycon \
+replace -replace \
+retocomplex -retocomplex \
+rhopot -rhopot \
+rotuvb -rotuvb \
+runavg -runavg \
+runmax -runmax \
+runmean -runmean \
+runmin -runmin \
+runpctl -runpctl \
+runstd -runstd \
+runstd1 -runstd1 \
+runsum -runsum \
+runvar -runvar \
+runvar1 -runvar1 \
+scatter -scatter \
+sealevelpressure -sealevelpressure \
+seasavg -seasavg \
+seascount -seascount \
+seasmax -seasmax \
+seasmean -seasmean \
+seasmin -seasmin \
+seaspctl -seaspctl \
+seasstd -seasstd \
+seasstd1 -seasstd1 \
+seassum -seassum \
+seasvar -seasvar \
+seasvar1 -seasvar1 \
+seinfo -seinfo \
+seinfoc -seinfoc \
+seinfon -seinfon \
+seinfop -seinfop \
+selall -selall \
+selcode -selcode \
+seldate -seldate \
+selday -selday \
+select -select \
+selgrid -selgrid \
+selgridname -selgridname \
+selhour -selhour \
+selindexbox -selindexbox \
+sellevel -sellevel \
+sellevidx -sellevidx \
+sellonlatbox -sellonlatbox \
+selltype -selltype \
+selmon -selmon \
+selmonth -selmonth \
+selname -selname \
+seloperator -seloperator \
+selparam -selparam \
+selrec -selrec \
+selseas -selseas \
+selseason -selseason \
+selsmon -selsmon \
+selstdname -selstdname \
+seltabnum -seltabnum \
+seltime -seltime \
+seltimestep -seltimestep \
+selvar -selvar \
+selyear -selyear \
+selzaxis -selzaxis \
+selzaxisname -selzaxisname \
+setcalendar -setcalendar \
+setcindexbox -setcindexbox \
+setclonlatbox -setclonlatbox \
+setcode -setcode \
+setcodetab -setcodetab \
+setctomiss -setctomiss \
+setdate -setdate \
+setday -setday \
+setgatt -setgatt \
+setgatts -setgatts \
+setgrid -setgrid \
+setgridarea -setgridarea \
+setgridmask -setgridmask \
+setgridnumber -setgridnumber \
+setgridtype -setgridtype \
+setgriduri -setgriduri \
+sethalo -sethalo \
+setlevel -setlevel \
+setltype -setltype \
+setmisstoc -setmisstoc \
+setmisstodis -setmisstodis \
+setmisstonn -setmisstonn \
+setmissval -setmissval \
+setmon -setmon \
+setname -setname \
+setparam -setparam \
+setpartab -setpartab \
+setpartabc -setpartabc \
+setpartabn -setpartabn \
+setpartabp -setpartabp \
+setpartabv -setpartabv \
+setrcaname -setrcaname \
+setreftime -setreftime \
+setrtoc -setrtoc \
+setrtoc2 -setrtoc2 \
+setrtomiss -setrtomiss \
+settabnum -settabnum \
+settaxis -settaxis \
+settbounds -settbounds \
+settime -settime \
+settunits -settunits \
+setunit -setunit \
+setvals -setvals \
+setvar -setvar \
+setvrange -setvrange \
+setyear -setyear \
+setzaxis -setzaxis \
+shaded -shaded \
+shifttime -shifttime \
+showcode -showcode \
+showdate -showdate \
+showformat -showformat \
+showlevel -showlevel \
+showltype -showltype \
+showmon -showmon \
+showname -showname \
+showparam -showparam \
+showstdname -showstdname \
+showtime -showtime \
+showtimestamp -showtimestamp \
+showunit -showunit \
+showvar -showvar \
+showyear -showyear \
+sin -sin \
+sincos -sincos \
+sinfo -sinfo \
+sinfoc -sinfoc \
+sinfon -sinfon \
+sinfop -sinfop \
+sinfov -sinfov \
+smooth -smooth \
+smooth9 -smooth9 \
+sort -sort \
+sortcode -sortcode \
+sortlevel -sortlevel \
+sortname -sortname \
+sortparam -sortparam \
+sorttaxis -sorttaxis \
+sorttimestamp -sorttimestamp \
+sortvar -sortvar \
+sp2fc -sp2fc \
+sp2gp -sp2gp \
+sp2gpl -sp2gpl \
+sp2sp -sp2sp \
+spartab -spartab \
+spcut -spcut \
+specinfo -specinfo \
+spectrum -spectrum \
+splitcode -splitcode \
+splitday -splitday \
+splitgrid -splitgrid \
+splithour -splithour \
+splitlevel -splitlevel \
+splitmon -splitmon \
+splitname -splitname \
+splitparam -splitparam \
+splitrec -splitrec \
+splitseas -splitseas \
+splitsel -splitsel \
+splittabnum -splittabnum \
+splitvar -splitvar \
+splityear -splityear \
+splityearmon -splityearmon \
+splitzaxis -splitzaxis \
+sqr -sqr \
+sqrt -sqrt \
+stdatm -stdatm \
+strbre -strbre \
+strgal -strgal \
+strwin -strwin \
+sub -sub \
+subc -subc \
+subtrend -subtrend \
+szip -szip \
+tan -tan \
+tee -tee \
+temp -temp \
+thinout -thinout \
+timavg -timavg \
+timcor -timcor \
+timcount -timcount \
+timcovar -timcovar \
+timedt -timedt \
+timmax -timmax \
+timmean -timmean \
+timmin -timmin \
+timpctl -timpctl \
+timselavg -timselavg \
+timselmax -timselmax \
+timselmean -timselmean \
+timselmin -timselmin \
+timselpctl -timselpctl \
+timselstd -timselstd \
+timselstd1 -timselstd1 \
+timselsum -timselsum \
+timselvar -timselvar \
+timselvar1 -timselvar1 \
+timsort -timsort \
+timstd -timstd \
+timstd1 -timstd1 \
+timsum -timsum \
+timvar -timvar \
+timvar1 -timvar1 \
+tinfo -tinfo \
+topo -topo \
+tpnhalo -tpnhalo \
+transxy -transxy \
+trend -trend \
+tstepcount -tstepcount \
+unsetgridmask -unsetgridmask \
+uv2dv -uv2dv \
+uv2dvl -uv2dvl \
+vardes -vardes \
+varquot2test -varquot2test \
+vct -vct \
+vct2 -vct2 \
+vector -vector \
+verifygrid -verifygrid \
+vertavg -vertavg \
+vertcum -vertcum \
+vertcumhl -vertcumhl \
+vertint -vertint \
+vertmax -vertmax \
+vertmean -vertmean \
+vertmin -vertmin \
+vertstd -vertstd \
+vertstd1 -vertstd1 \
+vertsum -vertsum \
+vertvar -vertvar \
+vertvar1 -vertvar1 \
+vertwind -vertwind \
+vlist -vlist \
+wct -wct \
+writegrid -writegrid \
+writerandom -writerandom \
+ydayadd -ydayadd \
+ydayavg -ydayavg \
+ydaydiv -ydaydiv \
+ydaymax -ydaymax \
+ydaymean -ydaymean \
+ydaymin -ydaymin \
+ydaymul -ydaymul \
+ydaypctl -ydaypctl \
+ydaystd -ydaystd \
+ydaystd1 -ydaystd1 \
+ydaysub -ydaysub \
+ydaysum -ydaysum \
+ydayvar -ydayvar \
+ydayvar1 -ydayvar1 \
+ydrunavg -ydrunavg \
+ydrunmax -ydrunmax \
+ydrunmean -ydrunmean \
+ydrunmin -ydrunmin \
+ydrunpctl -ydrunpctl \
+ydrunstd -ydrunstd \
+ydrunstd1 -ydrunstd1 \
+ydrunsum -ydrunsum \
+ydrunvar -ydrunvar \
+ydrunvar1 -ydrunvar1 \
+yearavg -yearavg \
+yearcount -yearcount \
+yearmax -yearmax \
+yearmean -yearmean \
+yearmin -yearmin \
+yearmonavg -yearmonavg \
+yearmonmean -yearmonmean \
+yearpctl -yearpctl \
+yearstd -yearstd \
+yearstd1 -yearstd1 \
+yearsum -yearsum \
+yearvar -yearvar \
+yearvar1 -yearvar1 \
+yhouradd -yhouradd \
+yhouravg -yhouravg \
+yhourdiv -yhourdiv \
+yhourmax -yhourmax \
+yhourmean -yhourmean \
+yhourmin -yhourmin \
+yhourmul -yhourmul \
+yhourstd -yhourstd \
+yhourstd1 -yhourstd1 \
+yhoursub -yhoursub \
+yhoursum -yhoursum \
+yhourvar -yhourvar \
+yhourvar1 -yhourvar1 \
+ymonadd -ymonadd \
+ymonavg -ymonavg \
+ymondiv -ymondiv \
+ymonmax -ymonmax \
+ymonmean -ymonmean \
+ymonmin -ymonmin \
+ymonmul -ymonmul \
+ymonpctl -ymonpctl \
+ymonstd -ymonstd \
+ymonstd1 -ymonstd1 \
+ymonsub -ymonsub \
+ymonsum -ymonsum \
+ymonvar -ymonvar \
+ymonvar1 -ymonvar1 \
+yseasadd -yseasadd \
+yseasavg -yseasavg \
+yseasdiv -yseasdiv \
+yseasmax -yseasmax \
+yseasmean -yseasmean \
+yseasmin -yseasmin \
+yseasmul -yseasmul \
+yseaspctl -yseaspctl \
+yseasstd -yseasstd \
+yseasstd1 -yseasstd1 \
+yseassub -yseassub \
+yseassum -yseassum \
+yseasvar -yseasvar \
+yseasvar1 -yseasvar1 \
+zaxisdes -zaxisdes \
+zonavg -zonavg \
+zonmax -zonmax \
+zonmean -zonmean \
+zonmin -zonmin \
+zonpctl -zonpctl \
+zonrange -zonrange \
+zonstd -zonstd \
+zonstd1 -zonstd1 \
+zonsum -zonsum \
+zonvar -zonvar \
+zonvar1 -zonvar1 \
 " -f cdo
diff --git a/contrib/cdoCompletion.tcsh b/contrib/cdoCompletion.tcsh
index ab97758..abfbcef 100644
--- a/contrib/cdoCompletion.tcsh
+++ b/contrib/cdoCompletion.tcsh
@@ -1,39 +1,778 @@
 set cdoCmpl = (\
-- \
-- \
-- \
-- \
-- \
-- \
-- \
+-cmor \
+-enableexcept \
+-history \
+-netcdf_hdr_pad, \
+-no_warnings \
+-operators \
+-percentile \
+-reduce_dim \
+-sort \
+-timestat_date \
+C, \
 L \
 M \
 O \
 P \
-Q \
-R \
+R, \
 S \
-V \
+V, \
 W \
 a \
 b \
-f \
+f, \
 g \
-h \
+h, \
 k \
 m \
 r \
-s \
+s, \
 t \
-v \
+v, \
 z \
---operators \
-Use \
-a \
-all \
+abs \
+acos \
+add \
+addc \
+adipot \
+adisit \
+aexpr \
+aexprf \
+after \
+afterburner \
+anomaly \
+ap2hl \
+ap2hlx \
+ap2pl \
+ap2pl_lp \
+ap2plx \
+ap2plx_lp \
+asin \
+atan \
+atan2 \
+bandpass \
+boxavg \
+cat \
+cdiread \
+cdiwrite \
+chcode \
+chlevel \
+chlevelc \
+chlevelv \
+chltype \
+chname \
+chparam \
+chtabnum \
+chunit \
+chvar \
+cloudlayer \
+cmor \
+codetab \
+collgrid \
+complextorect \
+consecsum \
+consects \
+const \
+contour \
+conv_cmor_table \
+copy \
+cos \
+coshill \
+covar0 \
+covar0r \
+dayavg \
+daycount \
+daymax \
+daymean \
+daymin \
+daypctl \
+daystd \
+daystd1 \
+daysum \
+dayvar \
+dayvar1 \
+del29feb \
+delcode \
+delday \
+delete \
+delname \
+delparam \
+deltap \
+deltap_fl \
+delvar \
+detrend \
+diff \
+diffc \
+diffn \
+diffp \
+diffv \
+distgrid \
+div \
+divc \
+divcoslat \
+divdpm \
+divdpy \
+dumpmap \
+duplicate \
+dv2ps \
+dv2uv \
+dv2uvl \
+eca_cdd \
+eca_cfd \
+eca_csu \
+eca_cwd \
+eca_cwdi \
+eca_cwfi \
+eca_etr \
+eca_fd \
+eca_gsl \
+eca_hd \
+eca_hwdi \
+eca_hwfi \
+eca_id \
+eca_pd \
+eca_r10mm \
+eca_r1mm \
+eca_r20mm \
+eca_r75p \
+eca_r75ptot \
+eca_r90p \
+eca_r90ptot \
+eca_r95p \
+eca_r95ptot \
+eca_r99p \
+eca_r99ptot \
+eca_rr1 \
+eca_rx1day \
+eca_rx5day \
+eca_sdii \
+eca_su \
+eca_tg10p \
+eca_tg90p \
+eca_tn10p \
+eca_tn90p \
+eca_tr \
+eca_tx10p \
+eca_tx90p \
+enlarge \
+ensavg \
+ensbrs \
+enscrps \
+ensmax \
+ensmean \
+ensmin \
+enspctl \
+ensrkhist_space \
+ensrkhist_time \
+ensrkhistspace \
+ensrkhisttime \
+ensroc \
+ensstd \
+ensstd1 \
+enssum \
+ensvar \
+ensvar1 \
+eof \
+eof3d \
+eof3dspatial \
+eof3dtime \
+eofcoeff \
+eofcoeff3d \
+eofspatial \
+eoftime \
+eq \
+eqc \
+exp \
+export_e5ml \
+export_e5res \
+expr \
+exprf \
+fc2gp \
+fc2sp \
+fdns \
+filedes \
+fillmiss \
+fillmiss2 \
+fldavg \
+fldcor \
+fldcovar \
+fldmax \
+fldmean \
+fldmin \
+fldpctl \
+fldrms \
+fldstd \
+fldstd1 \
+fldsum \
+fldvar \
+fldvar1 \
 for \
-list \
-of \
-operators. \
-option \
+fourier \
+fpressure \
+gather \
+ge \
+gec \
+genbic \
+genbil \
+gencon \
+gencon2 \
+gendis \
+gengrid \
+genlaf \
+genlevelbounds \
+gennn \
+genycon \
+geopotheight \
+ggstat \
+ggstats \
+gheight \
+globavg \
+gmtcells \
+gmtxyz \
+gp2fc \
+gp2sp \
+gp2spl \
+gradsdes \
+graph \
+grfill \
+gridarea \
+gridboxavg \
+gridboxmax \
+gridboxmean \
+gridboxmin \
+gridboxstd \
+gridboxstd1 \
+gridboxsum \
+gridboxvar \
+gridboxvar1 \
+griddes \
+griddes2 \
+griddx \
+griddy \
+gridmask \
+gridverify \
+gridweights \
+gt \
+gtc \
+harmonic \
+highpass \
+histcount \
+histfreq \
+histmean \
+histsum \
+houravg \
+hourcount \
+hourmax \
+hourmean \
+hourmin \
+hourpctl \
+hourstd \
+hourstd1 \
+hoursum \
+hourvar \
+hourvar1 \
+hpressure \
+hurr \
+ifnotthen \
+ifnotthenc \
+ifthen \
+ifthenc \
+ifthenelse \
+import_amsr \
+import_binary \
+import_cmsaf \
+import_e5ml \
+import_e5res \
+import_grads \
+import_obs \
+imtocomplex \
+info \
+infoc \
+infon \
+infop \
+infos \
+infov \
+input \
+inputext \
+inputsrv \
+int \
+interpolate \
+intgrid \
+intgridbil \
+intgridcon \
+intgridtraj \
+intlevel \
+intlevel3d \
+intlevelx \
+intlevelx3d \
+intntime \
+intpoint \
+inttime \
+intyear \
+invertlat \
+invertlatdata \
+invertlatdes \
+invertlev \
+invertlon \
+invertlondata \
+invertlondes \
+isosurface \
+le \
+lec \
+lmavg \
+lmean \
+lmmean \
+lmstd \
+ln \
+log \
+log10 \
+lowpass \
+lsmean \
+lt \
+ltc \
+map \
+mask \
+maskindexbox \
+masklonlatbox \
+maskregion \
+mastrfu \
+max \
+meandiff2test \
+meravg \
+merge \
+mergegrid \
+mergetime \
+mermax \
+mermean \
+mermin \
+merpctl \
+merstd \
+merstd1 \
+mersum \
+mervar \
+mervar1 \
+min \
+ml2hl \
+ml2hl_lp \
+ml2hlx \
+ml2hlx_lp \
+ml2pl \
+ml2pl_lp \
+ml2plx \
+ml2plx_lp \
+mod \
+monadd \
+monavg \
+moncount \
+mondiv \
+monmax \
+monmean \
+monmin \
+monmul \
+monpctl \
+monstd \
+monstd1 \
+monsub \
+monsum \
+monvar \
+monvar1 \
+mrotuv \
+mrotuvb \
+mul \
+mulc \
+mulcoslat \
+muldoy \
+muldpm \
+muldpy \
+ncode \
+ncode \
+ncopy \
+ndate \
+ne \
+nec \
+ngridpoints \
+ngrids \
+nint \
+nlevel \
+nmon \
+npar \
+ntime \
+nvar \
+nyear \
+output \
+outputarr \
+outputbounds \
+outputboundscpt \
+outputcenter \
+outputcenter2 \
+outputcentercpt \
+outputext \
+outputf \
+outputfld \
+outputint \
+outputkey \
+outputsrv \
+outputtab \
+outputtri \
+outputts \
+outputvector \
+outputvrml \
+outputxyz \
+pack \
+pardes \
+pardup \
+parmul \
+partab \
+partab2 \
+pinfo \
+pinfov \
+pow \
+pressure_fl \
+pressure_hl \
+random \
+read_cmor_table \
+reci \
+reducegrid \
+regres \
+remap \
+remapbic \
+remapbil \
+remapcon \
+remapcon1 \
+remapcon2 \
+remapdis \
+remapdis1 \
+remapeta \
+remapeta_s \
+remapeta_z \
+remaplaf \
+remapnn \
+remapsum \
+remapycon \
+replace \
+retocomplex \
+rhopot \
+rotuvb \
+runavg \
+runmax \
+runmean \
+runmin \
+runpctl \
+runstd \
+runstd1 \
+runsum \
+runvar \
+runvar1 \
+scatter \
+sealevelpressure \
+seasavg \
+seascount \
+seasmax \
+seasmean \
+seasmin \
+seaspctl \
+seasstd \
+seasstd1 \
+seassum \
+seasvar \
+seasvar1 \
+seinfo \
+seinfoc \
+seinfon \
+seinfop \
+selall \
+selcode \
+seldate \
+selday \
+select \
+selgrid \
+selgridname \
+selhour \
+selindexbox \
+sellevel \
+sellevidx \
+sellonlatbox \
+selltype \
+selmon \
+selmonth \
+selname \
+seloperator \
+selparam \
+selrec \
+selseas \
+selseason \
+selsmon \
+selstdname \
+seltabnum \
+seltime \
+seltimestep \
+selvar \
+selyear \
+selzaxis \
+selzaxisname \
+setcalendar \
+setcindexbox \
+setclonlatbox \
+setcode \
+setcodetab \
+setctomiss \
+setdate \
+setday \
+setgatt \
+setgatts \
+setgrid \
+setgridarea \
+setgridmask \
+setgridnumber \
+setgridtype \
+setgriduri \
+sethalo \
+setlevel \
+setltype \
+setmisstoc \
+setmisstodis \
+setmisstonn \
+setmissval \
+setmon \
+setname \
+setparam \
+setpartab \
+setpartabc \
+setpartabn \
+setpartabp \
+setpartabv \
+setrcaname \
+setreftime \
+setrtoc \
+setrtoc2 \
+setrtomiss \
+settabnum \
+settaxis \
+settbounds \
+settime \
+settunits \
+setunit \
+setvals \
+setvar \
+setvrange \
+setyear \
+setzaxis \
+shaded \
+shifttime \
+showcode \
+showdate \
+showformat \
+showlevel \
+showltype \
+showmon \
+showname \
+showparam \
+showstdname \
+showtime \
+showtimestamp \
+showunit \
+showvar \
+showyear \
+sin \
+sincos \
+sinfo \
+sinfoc \
+sinfon \
+sinfop \
+sinfov \
+smooth \
+smooth9 \
+sort \
+sortcode \
+sortlevel \
+sortname \
+sortparam \
+sorttaxis \
+sorttimestamp \
+sortvar \
+sp2fc \
+sp2gp \
+sp2gpl \
+sp2sp \
+spartab \
+spcut \
+specinfo \
+spectrum \
+splitcode \
+splitday \
+splitgrid \
+splithour \
+splitlevel \
+splitmon \
+splitname \
+splitparam \
+splitrec \
+splitseas \
+splitsel \
+splittabnum \
+splitvar \
+splityear \
+splityearmon \
+splitzaxis \
+sqr \
+sqrt \
+stdatm \
+strbre \
+strgal \
+strwin \
+sub \
+subc \
+subtrend \
+szip \
+tan \
+tee \
+temp \
+thinout \
+timavg \
+timcor \
+timcount \
+timcovar \
+timedt \
+timmax \
+timmean \
+timmin \
+timpctl \
+timselavg \
+timselmax \
+timselmean \
+timselmin \
+timselpctl \
+timselstd \
+timselstd1 \
+timselsum \
+timselvar \
+timselvar1 \
+timsort \
+timstd \
+timstd1 \
+timsum \
+timvar \
+timvar1 \
+tinfo \
+topo \
+tpnhalo \
+transxy \
+trend \
+tstepcount \
+unsetgridmask \
+uv2dv \
+uv2dvl \
+vardes \
+varquot2test \
+vct \
+vct2 \
+vector \
+verifygrid \
+vertavg \
+vertcum \
+vertcumhl \
+vertint \
+vertmax \
+vertmean \
+vertmin \
+vertstd \
+vertstd1 \
+vertsum \
+vertvar \
+vertvar1 \
+vertwind \
+vlist \
+wct \
+writegrid \
+writerandom \
+ydayadd \
+ydayavg \
+ydaydiv \
+ydaymax \
+ydaymean \
+ydaymin \
+ydaymul \
+ydaypctl \
+ydaystd \
+ydaystd1 \
+ydaysub \
+ydaysum \
+ydayvar \
+ydayvar1 \
+ydrunavg \
+ydrunmax \
+ydrunmean \
+ydrunmin \
+ydrunpctl \
+ydrunstd \
+ydrunstd1 \
+ydrunsum \
+ydrunvar \
+ydrunvar1 \
+yearavg \
+yearcount \
+yearmax \
+yearmean \
+yearmin \
+yearmonavg \
+yearmonmean \
+yearpctl \
+yearstd \
+yearstd1 \
+yearsum \
+yearvar \
+yearvar1 \
+yhouradd \
+yhouravg \
+yhourdiv \
+yhourmax \
+yhourmean \
+yhourmin \
+yhourmul \
+yhourstd \
+yhourstd1 \
+yhoursub \
+yhoursum \
+yhourvar \
+yhourvar1 \
+ymonadd \
+ymonavg \
+ymondiv \
+ymonmax \
+ymonmean \
+ymonmin \
+ymonmul \
+ymonpctl \
+ymonstd \
+ymonstd1 \
+ymonsub \
+ymonsum \
+ymonvar \
+ymonvar1 \
+yseasadd \
+yseasavg \
+yseasdiv \
+yseasmax \
+yseasmean \
+yseasmin \
+yseasmul \
+yseaspctl \
+yseasstd \
+yseasstd1 \
+yseassub \
+yseassum \
+yseasvar \
+yseasvar1 \
+zaxisdes \
+zonavg \
+zonmax \
+zonmean \
+zonmin \
+zonpctl \
+zonrange \
+zonstd \
+zonstd1 \
+zonsum \
+zonvar \
+zonvar1 \
 ); complete cdo 'c/-/$cdoCmpl/' 'n/*/f/'
diff --git a/contrib/cdoCompletion.zsh b/contrib/cdoCompletion.zsh
index af132a8..19a7d08 100644
--- a/contrib/cdoCompletion.zsh
+++ b/contrib/cdoCompletion.zsh
@@ -1,39 +1,778 @@
 compctl -k "(
--- \
--- \
--- \
--- \
--- \
--- \
--- \
+--cmor \
+--enableexcept \
+--history \
+--netcdf_hdr_pad, \
+--no_warnings \
+--operators \
+--percentile \
+--reduce_dim \
+--sort \
+--timestat_date \
+-C, \
 -L \
 -M \
 -O \
 -P \
--Q \
--R \
+-R, \
 -S \
--V \
+-V, \
 -W \
 -a \
 -b \
--f \
+-f, \
 -g \
--h \
+-h, \
 -k \
 -m \
 -r \
--s \
+-s, \
 -t \
--v \
+-v, \
 -z \
---operators ---operators \
-Use -Use \
-a -a \
-all -all \
+abs -abs \
+acos -acos \
+add -add \
+addc -addc \
+adipot -adipot \
+adisit -adisit \
+aexpr -aexpr \
+aexprf -aexprf \
+after -after \
+afterburner -afterburner \
+anomaly -anomaly \
+ap2hl -ap2hl \
+ap2hlx -ap2hlx \
+ap2pl -ap2pl \
+ap2pl_lp -ap2pl_lp \
+ap2plx -ap2plx \
+ap2plx_lp -ap2plx_lp \
+asin -asin \
+atan -atan \
+atan2 -atan2 \
+bandpass -bandpass \
+boxavg -boxavg \
+cat -cat \
+cdiread -cdiread \
+cdiwrite -cdiwrite \
+chcode -chcode \
+chlevel -chlevel \
+chlevelc -chlevelc \
+chlevelv -chlevelv \
+chltype -chltype \
+chname -chname \
+chparam -chparam \
+chtabnum -chtabnum \
+chunit -chunit \
+chvar -chvar \
+cloudlayer -cloudlayer \
+cmor -cmor \
+codetab -codetab \
+collgrid -collgrid \
+complextorect -complextorect \
+consecsum -consecsum \
+consects -consects \
+const -const \
+contour -contour \
+conv_cmor_table -conv_cmor_table \
+copy -copy \
+cos -cos \
+coshill -coshill \
+covar0 -covar0 \
+covar0r -covar0r \
+dayavg -dayavg \
+daycount -daycount \
+daymax -daymax \
+daymean -daymean \
+daymin -daymin \
+daypctl -daypctl \
+daystd -daystd \
+daystd1 -daystd1 \
+daysum -daysum \
+dayvar -dayvar \
+dayvar1 -dayvar1 \
+del29feb -del29feb \
+delcode -delcode \
+delday -delday \
+delete -delete \
+delname -delname \
+delparam -delparam \
+deltap -deltap \
+deltap_fl -deltap_fl \
+delvar -delvar \
+detrend -detrend \
+diff -diff \
+diffc -diffc \
+diffn -diffn \
+diffp -diffp \
+diffv -diffv \
+distgrid -distgrid \
+div -div \
+divc -divc \
+divcoslat -divcoslat \
+divdpm -divdpm \
+divdpy -divdpy \
+dumpmap -dumpmap \
+duplicate -duplicate \
+dv2ps -dv2ps \
+dv2uv -dv2uv \
+dv2uvl -dv2uvl \
+eca_cdd -eca_cdd \
+eca_cfd -eca_cfd \
+eca_csu -eca_csu \
+eca_cwd -eca_cwd \
+eca_cwdi -eca_cwdi \
+eca_cwfi -eca_cwfi \
+eca_etr -eca_etr \
+eca_fd -eca_fd \
+eca_gsl -eca_gsl \
+eca_hd -eca_hd \
+eca_hwdi -eca_hwdi \
+eca_hwfi -eca_hwfi \
+eca_id -eca_id \
+eca_pd -eca_pd \
+eca_r10mm -eca_r10mm \
+eca_r1mm -eca_r1mm \
+eca_r20mm -eca_r20mm \
+eca_r75p -eca_r75p \
+eca_r75ptot -eca_r75ptot \
+eca_r90p -eca_r90p \
+eca_r90ptot -eca_r90ptot \
+eca_r95p -eca_r95p \
+eca_r95ptot -eca_r95ptot \
+eca_r99p -eca_r99p \
+eca_r99ptot -eca_r99ptot \
+eca_rr1 -eca_rr1 \
+eca_rx1day -eca_rx1day \
+eca_rx5day -eca_rx5day \
+eca_sdii -eca_sdii \
+eca_su -eca_su \
+eca_tg10p -eca_tg10p \
+eca_tg90p -eca_tg90p \
+eca_tn10p -eca_tn10p \
+eca_tn90p -eca_tn90p \
+eca_tr -eca_tr \
+eca_tx10p -eca_tx10p \
+eca_tx90p -eca_tx90p \
+enlarge -enlarge \
+ensavg -ensavg \
+ensbrs -ensbrs \
+enscrps -enscrps \
+ensmax -ensmax \
+ensmean -ensmean \
+ensmin -ensmin \
+enspctl -enspctl \
+ensrkhist_space -ensrkhist_space \
+ensrkhist_time -ensrkhist_time \
+ensrkhistspace -ensrkhistspace \
+ensrkhisttime -ensrkhisttime \
+ensroc -ensroc \
+ensstd -ensstd \
+ensstd1 -ensstd1 \
+enssum -enssum \
+ensvar -ensvar \
+ensvar1 -ensvar1 \
+eof -eof \
+eof3d -eof3d \
+eof3dspatial -eof3dspatial \
+eof3dtime -eof3dtime \
+eofcoeff -eofcoeff \
+eofcoeff3d -eofcoeff3d \
+eofspatial -eofspatial \
+eoftime -eoftime \
+eq -eq \
+eqc -eqc \
+exp -exp \
+export_e5ml -export_e5ml \
+export_e5res -export_e5res \
+expr -expr \
+exprf -exprf \
+fc2gp -fc2gp \
+fc2sp -fc2sp \
+fdns -fdns \
+filedes -filedes \
+fillmiss -fillmiss \
+fillmiss2 -fillmiss2 \
+fldavg -fldavg \
+fldcor -fldcor \
+fldcovar -fldcovar \
+fldmax -fldmax \
+fldmean -fldmean \
+fldmin -fldmin \
+fldpctl -fldpctl \
+fldrms -fldrms \
+fldstd -fldstd \
+fldstd1 -fldstd1 \
+fldsum -fldsum \
+fldvar -fldvar \
+fldvar1 -fldvar1 \
 for -for \
-list -list \
-of -of \
-operators. -operators. \
-option -option \
+fourier -fourier \
+fpressure -fpressure \
+gather -gather \
+ge -ge \
+gec -gec \
+genbic -genbic \
+genbil -genbil \
+gencon -gencon \
+gencon2 -gencon2 \
+gendis -gendis \
+gengrid -gengrid \
+genlaf -genlaf \
+genlevelbounds -genlevelbounds \
+gennn -gennn \
+genycon -genycon \
+geopotheight -geopotheight \
+ggstat -ggstat \
+ggstats -ggstats \
+gheight -gheight \
+globavg -globavg \
+gmtcells -gmtcells \
+gmtxyz -gmtxyz \
+gp2fc -gp2fc \
+gp2sp -gp2sp \
+gp2spl -gp2spl \
+gradsdes -gradsdes \
+graph -graph \
+grfill -grfill \
+gridarea -gridarea \
+gridboxavg -gridboxavg \
+gridboxmax -gridboxmax \
+gridboxmean -gridboxmean \
+gridboxmin -gridboxmin \
+gridboxstd -gridboxstd \
+gridboxstd1 -gridboxstd1 \
+gridboxsum -gridboxsum \
+gridboxvar -gridboxvar \
+gridboxvar1 -gridboxvar1 \
+griddes -griddes \
+griddes2 -griddes2 \
+griddx -griddx \
+griddy -griddy \
+gridmask -gridmask \
+gridverify -gridverify \
+gridweights -gridweights \
+gt -gt \
+gtc -gtc \
+harmonic -harmonic \
+highpass -highpass \
+histcount -histcount \
+histfreq -histfreq \
+histmean -histmean \
+histsum -histsum \
+houravg -houravg \
+hourcount -hourcount \
+hourmax -hourmax \
+hourmean -hourmean \
+hourmin -hourmin \
+hourpctl -hourpctl \
+hourstd -hourstd \
+hourstd1 -hourstd1 \
+hoursum -hoursum \
+hourvar -hourvar \
+hourvar1 -hourvar1 \
+hpressure -hpressure \
+hurr -hurr \
+ifnotthen -ifnotthen \
+ifnotthenc -ifnotthenc \
+ifthen -ifthen \
+ifthenc -ifthenc \
+ifthenelse -ifthenelse \
+import_amsr -import_amsr \
+import_binary -import_binary \
+import_cmsaf -import_cmsaf \
+import_e5ml -import_e5ml \
+import_e5res -import_e5res \
+import_grads -import_grads \
+import_obs -import_obs \
+imtocomplex -imtocomplex \
+info -info \
+infoc -infoc \
+infon -infon \
+infop -infop \
+infos -infos \
+infov -infov \
+input -input \
+inputext -inputext \
+inputsrv -inputsrv \
+int -int \
+interpolate -interpolate \
+intgrid -intgrid \
+intgridbil -intgridbil \
+intgridcon -intgridcon \
+intgridtraj -intgridtraj \
+intlevel -intlevel \
+intlevel3d -intlevel3d \
+intlevelx -intlevelx \
+intlevelx3d -intlevelx3d \
+intntime -intntime \
+intpoint -intpoint \
+inttime -inttime \
+intyear -intyear \
+invertlat -invertlat \
+invertlatdata -invertlatdata \
+invertlatdes -invertlatdes \
+invertlev -invertlev \
+invertlon -invertlon \
+invertlondata -invertlondata \
+invertlondes -invertlondes \
+isosurface -isosurface \
+le -le \
+lec -lec \
+lmavg -lmavg \
+lmean -lmean \
+lmmean -lmmean \
+lmstd -lmstd \
+ln -ln \
+log -log \
+log10 -log10 \
+lowpass -lowpass \
+lsmean -lsmean \
+lt -lt \
+ltc -ltc \
+map -map \
+mask -mask \
+maskindexbox -maskindexbox \
+masklonlatbox -masklonlatbox \
+maskregion -maskregion \
+mastrfu -mastrfu \
+max -max \
+meandiff2test -meandiff2test \
+meravg -meravg \
+merge -merge \
+mergegrid -mergegrid \
+mergetime -mergetime \
+mermax -mermax \
+mermean -mermean \
+mermin -mermin \
+merpctl -merpctl \
+merstd -merstd \
+merstd1 -merstd1 \
+mersum -mersum \
+mervar -mervar \
+mervar1 -mervar1 \
+min -min \
+ml2hl -ml2hl \
+ml2hl_lp -ml2hl_lp \
+ml2hlx -ml2hlx \
+ml2hlx_lp -ml2hlx_lp \
+ml2pl -ml2pl \
+ml2pl_lp -ml2pl_lp \
+ml2plx -ml2plx \
+ml2plx_lp -ml2plx_lp \
+mod -mod \
+monadd -monadd \
+monavg -monavg \
+moncount -moncount \
+mondiv -mondiv \
+monmax -monmax \
+monmean -monmean \
+monmin -monmin \
+monmul -monmul \
+monpctl -monpctl \
+monstd -monstd \
+monstd1 -monstd1 \
+monsub -monsub \
+monsum -monsum \
+monvar -monvar \
+monvar1 -monvar1 \
+mrotuv -mrotuv \
+mrotuvb -mrotuvb \
+mul -mul \
+mulc -mulc \
+mulcoslat -mulcoslat \
+muldoy -muldoy \
+muldpm -muldpm \
+muldpy -muldpy \
+ncode -ncode \
+ncode -ncode \
+ncopy -ncopy \
+ndate -ndate \
+ne -ne \
+nec -nec \
+ngridpoints -ngridpoints \
+ngrids -ngrids \
+nint -nint \
+nlevel -nlevel \
+nmon -nmon \
+npar -npar \
+ntime -ntime \
+nvar -nvar \
+nyear -nyear \
+output -output \
+outputarr -outputarr \
+outputbounds -outputbounds \
+outputboundscpt -outputboundscpt \
+outputcenter -outputcenter \
+outputcenter2 -outputcenter2 \
+outputcentercpt -outputcentercpt \
+outputext -outputext \
+outputf -outputf \
+outputfld -outputfld \
+outputint -outputint \
+outputkey -outputkey \
+outputsrv -outputsrv \
+outputtab -outputtab \
+outputtri -outputtri \
+outputts -outputts \
+outputvector -outputvector \
+outputvrml -outputvrml \
+outputxyz -outputxyz \
+pack -pack \
+pardes -pardes \
+pardup -pardup \
+parmul -parmul \
+partab -partab \
+partab2 -partab2 \
+pinfo -pinfo \
+pinfov -pinfov \
+pow -pow \
+pressure_fl -pressure_fl \
+pressure_hl -pressure_hl \
+random -random \
+read_cmor_table -read_cmor_table \
+reci -reci \
+reducegrid -reducegrid \
+regres -regres \
+remap -remap \
+remapbic -remapbic \
+remapbil -remapbil \
+remapcon -remapcon \
+remapcon1 -remapcon1 \
+remapcon2 -remapcon2 \
+remapdis -remapdis \
+remapdis1 -remapdis1 \
+remapeta -remapeta \
+remapeta_s -remapeta_s \
+remapeta_z -remapeta_z \
+remaplaf -remaplaf \
+remapnn -remapnn \
+remapsum -remapsum \
+remapycon -remapycon \
+replace -replace \
+retocomplex -retocomplex \
+rhopot -rhopot \
+rotuvb -rotuvb \
+runavg -runavg \
+runmax -runmax \
+runmean -runmean \
+runmin -runmin \
+runpctl -runpctl \
+runstd -runstd \
+runstd1 -runstd1 \
+runsum -runsum \
+runvar -runvar \
+runvar1 -runvar1 \
+scatter -scatter \
+sealevelpressure -sealevelpressure \
+seasavg -seasavg \
+seascount -seascount \
+seasmax -seasmax \
+seasmean -seasmean \
+seasmin -seasmin \
+seaspctl -seaspctl \
+seasstd -seasstd \
+seasstd1 -seasstd1 \
+seassum -seassum \
+seasvar -seasvar \
+seasvar1 -seasvar1 \
+seinfo -seinfo \
+seinfoc -seinfoc \
+seinfon -seinfon \
+seinfop -seinfop \
+selall -selall \
+selcode -selcode \
+seldate -seldate \
+selday -selday \
+select -select \
+selgrid -selgrid \
+selgridname -selgridname \
+selhour -selhour \
+selindexbox -selindexbox \
+sellevel -sellevel \
+sellevidx -sellevidx \
+sellonlatbox -sellonlatbox \
+selltype -selltype \
+selmon -selmon \
+selmonth -selmonth \
+selname -selname \
+seloperator -seloperator \
+selparam -selparam \
+selrec -selrec \
+selseas -selseas \
+selseason -selseason \
+selsmon -selsmon \
+selstdname -selstdname \
+seltabnum -seltabnum \
+seltime -seltime \
+seltimestep -seltimestep \
+selvar -selvar \
+selyear -selyear \
+selzaxis -selzaxis \
+selzaxisname -selzaxisname \
+setcalendar -setcalendar \
+setcindexbox -setcindexbox \
+setclonlatbox -setclonlatbox \
+setcode -setcode \
+setcodetab -setcodetab \
+setctomiss -setctomiss \
+setdate -setdate \
+setday -setday \
+setgatt -setgatt \
+setgatts -setgatts \
+setgrid -setgrid \
+setgridarea -setgridarea \
+setgridmask -setgridmask \
+setgridnumber -setgridnumber \
+setgridtype -setgridtype \
+setgriduri -setgriduri \
+sethalo -sethalo \
+setlevel -setlevel \
+setltype -setltype \
+setmisstoc -setmisstoc \
+setmisstodis -setmisstodis \
+setmisstonn -setmisstonn \
+setmissval -setmissval \
+setmon -setmon \
+setname -setname \
+setparam -setparam \
+setpartab -setpartab \
+setpartabc -setpartabc \
+setpartabn -setpartabn \
+setpartabp -setpartabp \
+setpartabv -setpartabv \
+setrcaname -setrcaname \
+setreftime -setreftime \
+setrtoc -setrtoc \
+setrtoc2 -setrtoc2 \
+setrtomiss -setrtomiss \
+settabnum -settabnum \
+settaxis -settaxis \
+settbounds -settbounds \
+settime -settime \
+settunits -settunits \
+setunit -setunit \
+setvals -setvals \
+setvar -setvar \
+setvrange -setvrange \
+setyear -setyear \
+setzaxis -setzaxis \
+shaded -shaded \
+shifttime -shifttime \
+showcode -showcode \
+showdate -showdate \
+showformat -showformat \
+showlevel -showlevel \
+showltype -showltype \
+showmon -showmon \
+showname -showname \
+showparam -showparam \
+showstdname -showstdname \
+showtime -showtime \
+showtimestamp -showtimestamp \
+showunit -showunit \
+showvar -showvar \
+showyear -showyear \
+sin -sin \
+sincos -sincos \
+sinfo -sinfo \
+sinfoc -sinfoc \
+sinfon -sinfon \
+sinfop -sinfop \
+sinfov -sinfov \
+smooth -smooth \
+smooth9 -smooth9 \
+sort -sort \
+sortcode -sortcode \
+sortlevel -sortlevel \
+sortname -sortname \
+sortparam -sortparam \
+sorttaxis -sorttaxis \
+sorttimestamp -sorttimestamp \
+sortvar -sortvar \
+sp2fc -sp2fc \
+sp2gp -sp2gp \
+sp2gpl -sp2gpl \
+sp2sp -sp2sp \
+spartab -spartab \
+spcut -spcut \
+specinfo -specinfo \
+spectrum -spectrum \
+splitcode -splitcode \
+splitday -splitday \
+splitgrid -splitgrid \
+splithour -splithour \
+splitlevel -splitlevel \
+splitmon -splitmon \
+splitname -splitname \
+splitparam -splitparam \
+splitrec -splitrec \
+splitseas -splitseas \
+splitsel -splitsel \
+splittabnum -splittabnum \
+splitvar -splitvar \
+splityear -splityear \
+splityearmon -splityearmon \
+splitzaxis -splitzaxis \
+sqr -sqr \
+sqrt -sqrt \
+stdatm -stdatm \
+strbre -strbre \
+strgal -strgal \
+strwin -strwin \
+sub -sub \
+subc -subc \
+subtrend -subtrend \
+szip -szip \
+tan -tan \
+tee -tee \
+temp -temp \
+thinout -thinout \
+timavg -timavg \
+timcor -timcor \
+timcount -timcount \
+timcovar -timcovar \
+timedt -timedt \
+timmax -timmax \
+timmean -timmean \
+timmin -timmin \
+timpctl -timpctl \
+timselavg -timselavg \
+timselmax -timselmax \
+timselmean -timselmean \
+timselmin -timselmin \
+timselpctl -timselpctl \
+timselstd -timselstd \
+timselstd1 -timselstd1 \
+timselsum -timselsum \
+timselvar -timselvar \
+timselvar1 -timselvar1 \
+timsort -timsort \
+timstd -timstd \
+timstd1 -timstd1 \
+timsum -timsum \
+timvar -timvar \
+timvar1 -timvar1 \
+tinfo -tinfo \
+topo -topo \
+tpnhalo -tpnhalo \
+transxy -transxy \
+trend -trend \
+tstepcount -tstepcount \
+unsetgridmask -unsetgridmask \
+uv2dv -uv2dv \
+uv2dvl -uv2dvl \
+vardes -vardes \
+varquot2test -varquot2test \
+vct -vct \
+vct2 -vct2 \
+vector -vector \
+verifygrid -verifygrid \
+vertavg -vertavg \
+vertcum -vertcum \
+vertcumhl -vertcumhl \
+vertint -vertint \
+vertmax -vertmax \
+vertmean -vertmean \
+vertmin -vertmin \
+vertstd -vertstd \
+vertstd1 -vertstd1 \
+vertsum -vertsum \
+vertvar -vertvar \
+vertvar1 -vertvar1 \
+vertwind -vertwind \
+vlist -vlist \
+wct -wct \
+writegrid -writegrid \
+writerandom -writerandom \
+ydayadd -ydayadd \
+ydayavg -ydayavg \
+ydaydiv -ydaydiv \
+ydaymax -ydaymax \
+ydaymean -ydaymean \
+ydaymin -ydaymin \
+ydaymul -ydaymul \
+ydaypctl -ydaypctl \
+ydaystd -ydaystd \
+ydaystd1 -ydaystd1 \
+ydaysub -ydaysub \
+ydaysum -ydaysum \
+ydayvar -ydayvar \
+ydayvar1 -ydayvar1 \
+ydrunavg -ydrunavg \
+ydrunmax -ydrunmax \
+ydrunmean -ydrunmean \
+ydrunmin -ydrunmin \
+ydrunpctl -ydrunpctl \
+ydrunstd -ydrunstd \
+ydrunstd1 -ydrunstd1 \
+ydrunsum -ydrunsum \
+ydrunvar -ydrunvar \
+ydrunvar1 -ydrunvar1 \
+yearavg -yearavg \
+yearcount -yearcount \
+yearmax -yearmax \
+yearmean -yearmean \
+yearmin -yearmin \
+yearmonavg -yearmonavg \
+yearmonmean -yearmonmean \
+yearpctl -yearpctl \
+yearstd -yearstd \
+yearstd1 -yearstd1 \
+yearsum -yearsum \
+yearvar -yearvar \
+yearvar1 -yearvar1 \
+yhouradd -yhouradd \
+yhouravg -yhouravg \
+yhourdiv -yhourdiv \
+yhourmax -yhourmax \
+yhourmean -yhourmean \
+yhourmin -yhourmin \
+yhourmul -yhourmul \
+yhourstd -yhourstd \
+yhourstd1 -yhourstd1 \
+yhoursub -yhoursub \
+yhoursum -yhoursum \
+yhourvar -yhourvar \
+yhourvar1 -yhourvar1 \
+ymonadd -ymonadd \
+ymonavg -ymonavg \
+ymondiv -ymondiv \
+ymonmax -ymonmax \
+ymonmean -ymonmean \
+ymonmin -ymonmin \
+ymonmul -ymonmul \
+ymonpctl -ymonpctl \
+ymonstd -ymonstd \
+ymonstd1 -ymonstd1 \
+ymonsub -ymonsub \
+ymonsum -ymonsum \
+ymonvar -ymonvar \
+ymonvar1 -ymonvar1 \
+yseasadd -yseasadd \
+yseasavg -yseasavg \
+yseasdiv -yseasdiv \
+yseasmax -yseasmax \
+yseasmean -yseasmean \
+yseasmin -yseasmin \
+yseasmul -yseasmul \
+yseaspctl -yseaspctl \
+yseasstd -yseasstd \
+yseasstd1 -yseasstd1 \
+yseassub -yseassub \
+yseassum -yseassum \
+yseasvar -yseasvar \
+yseasvar1 -yseasvar1 \
+zaxisdes -zaxisdes \
+zonavg -zonavg \
+zonmax -zonmax \
+zonmean -zonmean \
+zonmin -zonmin \
+zonpctl -zonpctl \
+zonrange -zonrange \
+zonstd -zonstd \
+zonstd1 -zonstd1 \
+zonsum -zonsum \
+zonvar -zonvar \
+zonvar1 -zonvar1 \
 )" -f cdo
diff --git a/contrib/makecompl.rb b/contrib/makecompl.rb
index 54e16e6..3917190 100755
--- a/contrib/makecompl.rb
+++ b/contrib/makecompl.rb
@@ -1,5 +1,6 @@
 #!/usr/bin/env ruby
 require 'optparse'
+require 'pp'
 
 $opts = {:bin => '../src/cdo',:outfile => 'cdoCompletion'}
 OptionParser.new do |o|
@@ -21,7 +22,7 @@ Supported shells are TCSH, BASH and ZSH. For tcsh completion is only performed
 for regular options and operators with prepended '-'. Bash and zsh also
 complete opertors without leading '-'.
 
-AUTHOR:  Ralf Mueller, ralf.mueller at zmaw.de
+AUTHOR:  Ralf Mueller, ralf.mueller at mpimet.mpg.de
 
 LICENSE: CDO's License
 END
@@ -31,7 +32,7 @@ end.parse!
 #=============================================================================== 
 def getOperators
   # try to run the CDO binary first
-  cmd       = $opts[:bin] + ' 2>&1'
+  cmd       = $opts[:bin] + ' --operators'
   help      = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
   if 5 >= help.size
     puts "Operators could not get listed by running the CDO binary (#{$opts[:bin]})"
@@ -42,23 +43,23 @@ def getOperators
       }
     }.flatten
   else
-    help[(help.index("Operators:")+1)..help.index(help.find {|v| v =~ /CDO version/}) - 2].join(' ').split
+    help.map {|line| line.split[0]}
   end
 end
 def getOptions
-  cmd     = $opts[:bin] + ' 2>&1'
-  options = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}.find_all {|item| /^-/.match(item)}.map {|o| o[0,2]}
+  cmd     = $opts[:bin] + ' -h 2>&1'
+  options = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}.grep(/^--*\w+(,| )/).map {|line| line.split[0]}#{|item| /^-(-)\w+ /.match(item)}.map {|o| o[0,2]}
   if options.empty?
     puts "Commandline options could not get listed by running the CDO binary (#{$opts[:bin]})"
     puts "Go on processing operators only ..."
-    return []
+    exit 1
   end
   options
 end
 #=============================================================================== 
 operators = getOperators.sort
 options   = getOptions.sort
-# require 'pp'; pp operators; pp options
+#pp operators; pp options
 # Create the configuration files
 complCmds = { 
   :tcsh => ['set cdoCmpl = (\\','); complete cdo \'c/-/$cdoCmpl/\' \'n/*/f/\''],
diff --git a/doc/cdo.pdf b/doc/cdo.pdf
index f8d2ff9..f90f8bc 100644
Binary files a/doc/cdo.pdf and b/doc/cdo.pdf differ
diff --git a/doc/cdo_eca.pdf b/doc/cdo_eca.pdf
index d4cc2d5..bbf744a 100644
Binary files a/doc/cdo_eca.pdf and b/doc/cdo_eca.pdf differ
diff --git a/doc/cdo_magics.pdf b/doc/cdo_magics.pdf
index 0a19605..7c43b62 100644
Binary files a/doc/cdo_magics.pdf and b/doc/cdo_magics.pdf differ
diff --git a/doc/cdo_refcard.pdf b/doc/cdo_refcard.pdf
index 2115cf3..1f8d601 100644
Binary files a/doc/cdo_refcard.pdf and b/doc/cdo_refcard.pdf differ
diff --git a/libcdi/ChangeLog b/libcdi/ChangeLog
index bbc83d6..e9c44ad 100644
--- a/libcdi/ChangeLog
+++ b/libcdi/ChangeLog
@@ -1,3 +1,43 @@
+2016-06-??  Uwe Schulzweida
+
+	* Version 1.7.2 released
+
+2016-05-24 Uwe Schulzweida
+
+	* GRIB_API: added support for Gaussian reduced grids
+
+2016-05-23  Uwe Schulzweida
+
+	* zaxisTypeToGrib2ltype: added ZAXIS_DEPTH_BELOW_LAND (bug fix)
+
+2016-05-16  Uwe Schulzweida
+
+	* Seg fault in VCT with GRIB1 (introduced in 1.7.1) [Bug #6780]
+
+2016-04-29  Uwe Schulzweida
+
+	* gribapiDefLevel: replace grib_set_double(gh, "level", level) by grib2DefLevel() [Bug #6732]
+
+2016-04-27  Uwe Schulzweida
+
+	* cdfReadVarSlice: fix bug with DATATYPE_UINT8
+
+2016-04-04  Uwe Schulzweida
+
+	* GRIB1/GRIB_API (accumulation) encoding error [Bug #6638]
+
+2016-03-15  Uwe Schulzweida
+
+	* GRIB1 output with forecast times > 255 [Bug: #6600]
+
+2016-03-06  Uwe Schulzweida
+
+	* NetCDF: added support for dimension name of z axis
+
+2016-03-01  Uwe Schulzweida
+
+	* NetCDF: added support for dimension name of x and y axis
+
 2016-02-19  Uwe Schulzweida
 
 	* Version 1.7.1 released
diff --git a/libcdi/Makefile.am b/libcdi/Makefile.am
index b9848a7..d77e1b8 100644
--- a/libcdi/Makefile.am
+++ b/libcdi/Makefile.am
@@ -14,3 +14,9 @@ EXTRA_DIST=config/default \
 ACLOCAL_AMFLAGS = -I m4
 #
 CLEANFILES  = `ls *~`
+#
+doc/cdi_cman.pdf: 
+	(cd $(top_srcdir)/doc/tex ; ./makepdf_c ; mv cdi_cman.pdf .. ; ./cleanup)
+#
+doc/cdi_fman.pdf: 
+	(cd $(top_srcdir)/doc/tex ; ./makepdf_f ; mv cdi_fman.pdf .. ; ./cleanup)
diff --git a/libcdi/Makefile.in b/libcdi/Makefile.in
index ef20cd3..2639d34 100644
--- a/libcdi/Makefile.in
+++ b/libcdi/Makefile.in
@@ -264,6 +264,7 @@ ENABLE_IEG = @ENABLE_IEG@
 ENABLE_MPI = @ENABLE_MPI@
 ENABLE_NC2 = @ENABLE_NC2@
 ENABLE_NC4 = @ENABLE_NC4@
+ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
 ENABLE_NETCDF = @ENABLE_NETCDF@
 ENABLE_PYTHON = @ENABLE_PYTHON@
 ENABLE_RUBY = @ENABLE_RUBY@
@@ -286,9 +287,6 @@ GREP = @GREP@
 GRIB_API_INCLUDE = @GRIB_API_INCLUDE@
 GRIB_API_LIBS = @GRIB_API_LIBS@
 HAVE_PARALLEL_NC4 = @HAVE_PARALLEL_NC4@
-HDF5_INCLUDE = @HDF5_INCLUDE@
-HDF5_LIBS = @HDF5_LIBS@
-HDF5_ROOT = @HDF5_ROOT@
 HOST_NAME = @HOST_NAME@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -361,8 +359,6 @@ UUID_C_LIB = @UUID_C_LIB@
 VERSION = @VERSION@
 YAXT_CFLAGS = @YAXT_CFLAGS@
 YAXT_LIBS = @YAXT_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -911,6 +907,12 @@ uninstall-am:
 	mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
 	ps ps-am tags tags-am uninstall uninstall-am
 
+#
+doc/cdi_cman.pdf: 
+	(cd $(top_srcdir)/doc/tex ; ./makepdf_c ; mv cdi_cman.pdf .. ; ./cleanup)
+#
+doc/cdi_fman.pdf: 
+	(cd $(top_srcdir)/doc/tex ; ./makepdf_f ; mv cdi_fman.pdf .. ; ./cleanup)
 
 # 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/app/Makefile.am b/libcdi/app/Makefile.am
index 0fc7ff9..a9377d0 100644
--- a/libcdi/app/Makefile.am
+++ b/libcdi/app/Makefile.am
@@ -25,3 +25,8 @@ endif
 AM_CPPFLAGS         = -I$(top_srcdir)/src
 #
 CLEANFILES          = `ls *~`
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
diff --git a/libcdi/app/Makefile.in b/libcdi/app/Makefile.in
index f7be76b..1c1baf6 100644
--- a/libcdi/app/Makefile.in
+++ b/libcdi/app/Makefile.in
@@ -237,6 +237,7 @@ ENABLE_IEG = @ENABLE_IEG@
 ENABLE_MPI = @ENABLE_MPI@
 ENABLE_NC2 = @ENABLE_NC2@
 ENABLE_NC4 = @ENABLE_NC4@
+ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
 ENABLE_NETCDF = @ENABLE_NETCDF@
 ENABLE_PYTHON = @ENABLE_PYTHON@
 ENABLE_RUBY = @ENABLE_RUBY@
@@ -259,9 +260,6 @@ GREP = @GREP@
 GRIB_API_INCLUDE = @GRIB_API_INCLUDE@
 GRIB_API_LIBS = @GRIB_API_LIBS@
 HAVE_PARALLEL_NC4 = @HAVE_PARALLEL_NC4@
-HDF5_INCLUDE = @HDF5_INCLUDE@
-HDF5_LIBS = @HDF5_LIBS@
-HDF5_ROOT = @HDF5_ROOT@
 HOST_NAME = @HOST_NAME@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -334,8 +332,6 @@ UUID_C_LIB = @UUID_C_LIB@
 VERSION = @VERSION@
 YAXT_CFLAGS = @YAXT_CFLAGS@
 YAXT_LIBS = @YAXT_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -664,7 +660,7 @@ maintainer-clean-generic:
 	@echo "it deletes files that may require special tools to rebuild."
 clean: clean-am
 
-clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \
 	clean-noinstPROGRAMS mostlyclean-am
 
 distclean: distclean-am
@@ -736,7 +732,7 @@ uninstall-am: uninstall-binPROGRAMS
 .MAKE: install-am install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
-	clean-binPROGRAMS clean-generic clean-libtool \
+	clean-binPROGRAMS clean-generic clean-libtool clean-local \
 	clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
 	distclean-compile distclean-generic distclean-libtool \
 	distclean-tags distdir dvi dvi-am html html-am info info-am \
@@ -750,6 +746,11 @@ uninstall-am: uninstall-binPROGRAMS
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
 	tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
 
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
 
 # 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/app/cdi.c b/libcdi/app/cdi.c
index 8b32c5a..399b9b0 100644
--- a/libcdi/app/cdi.c
+++ b/libcdi/app/cdi.c
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
@@ -30,9 +31,8 @@ int      vlistInqVarMissvalUsed(int vlistID, int varID);
 #  define DBL_IS_EQUAL(x,y) (DBL_IS_NAN(x)||DBL_IS_NAN(y)?(DBL_IS_NAN(x)&&DBL_IS_NAN(y)?1:0):!(x < y || y < x))
 #endif
 
-#ifndef IS_EQUAL
+#ifndef IS_NOT_EQUAL
 #  define IS_NOT_EQUAL(x,y) (x < y || y < x)
-#  define IS_EQUAL(x,y)     (!IS_NOT_EQUAL(x,y))
 #endif
 
 #ifndef HOST_ENDIANNESS
@@ -102,8 +102,14 @@ void version(void)
 #if defined (_OPENMP)
   fprintf(stderr, " OpenMP");
 #endif
-#if  defined  (HAVE_NETCDF4)
+#if  defined(HAVE_NETCDF4)
   fprintf(stderr, " NC4");
+#if  defined(HAVE_NC4HDF5)
+  fprintf(stderr, "/HDF5");
+#if  defined(HAVE_NC4HDF5_THREADSAFE)
+  fprintf(stderr, "/threadsafe");
+#endif
+#endif
 #endif
 #if  defined  (HAVE_LIBNC_DAP)
   fprintf(stderr, " OPeNDAP");
@@ -111,9 +117,6 @@ void version(void)
 #if defined (HAVE_LIBSZ)
   fprintf(stderr, " SZ");
 #endif
-#if defined (HAVE_LIBZ)
-  fprintf(stderr, " Z");
-#endif
 #if defined (HAVE_LIBJASPER)
   fprintf(stderr, " JASPER");
 #endif
diff --git a/libcdi/app/printinfo.h b/libcdi/app/printinfo.h
index fe64df6..3a10ffe 100644
--- a/libcdi/app/printinfo.h
+++ b/libcdi/app/printinfo.h
@@ -1,5 +1,11 @@
 // This file is used in CDI and CDO !!!
 
+#if defined (HAVE_CONFIG_H)
+#  include "../src/config.h"
+#endif
+
+#include <stdio.h>
+
 #define DATE_FORMAT "%5.4d-%2.2d-%2.2d"
 #define TIME_FORMAT "%2.2d:%2.2d:%2.2d"
 
@@ -51,16 +57,16 @@ void printFiletype(int streamID, int vlistID)
       printf("GRIB2");
       break;
     case FILETYPE_NC:
-      printf("netCDF");
+      printf("NetCDF");
       break;
     case FILETYPE_NC2:
-      printf("netCDF2");
+      printf("NetCDF2");
       break;
     case FILETYPE_NC4:
-      printf("netCDF4");
+      printf("NetCDF4");
       break;
     case FILETYPE_NC4C:
-      printf("netCDF4 classic");
+      printf("NetCDF4 classic");
       break;
     case FILETYPE_SRV:
       printf("SERVICE");
@@ -134,21 +140,23 @@ void printFiletype(int streamID, int vlistID)
 static
 void printGridInfo(int vlistID)
 {
-  int ngrids, index;
-  int gridID, gridtype, trunc, gridsize, xsize, ysize, xysize;
   char xname[CDI_MAX_NAME], yname[CDI_MAX_NAME], xunits[CDI_MAX_NAME], yunits[CDI_MAX_NAME];
   unsigned char uuidOfHGrid[CDI_UUID_SIZE];
 
-  ngrids = vlistNgrids(vlistID);
-  for ( index = 0; index < ngrids; index++ )
+  int ngrids = vlistNgrids(vlistID);
+  for ( int index = 0; index < ngrids; index++ )
     {
-      gridID   = vlistGrid(vlistID, index);
-      gridtype = gridInqType(gridID);
-      trunc    = gridInqTrunc(gridID);
-      gridsize = gridInqSize(gridID);
-      xsize    = gridInqXsize(gridID);
-      ysize    = gridInqYsize(gridID);
-      xysize   = xsize*ysize;
+      int gridID   = vlistGrid(vlistID, index);
+      int gridtype = gridInqType(gridID);
+      int trunc    = gridInqTrunc(gridID);
+      int gridsize = gridInqSize(gridID);
+      int xsize    = gridInqXsize(gridID);
+      int ysize    = gridInqYsize(gridID);
+      int xysize   = xsize*ysize;
+      int prec     = gridInqPrec(gridID);
+
+      int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
+
       gridInqXname(gridID, xname);
       gridInqYname(gridID, yname);
       gridInqXunits(gridID, xunits);
@@ -164,14 +172,9 @@ void printGridInfo(int vlistID)
 	   gridtype == GRID_GAUSSIAN ||
 	   gridtype == GRID_GAUSSIAN_REDUCED )
 	{
-          int lxcoord = 1, lycoord = 1;
-	  double xfirst = 0.0, xlast = 0.0;
-	  double yfirst = 0.0, ylast = 0.0;
-	  double xinc = 0.0, yinc = 0.0;
-
-	  yfirst = gridInqYval(gridID, 0);
-	  ylast  = gridInqYval(gridID, ysize-1);
-	  yinc   = gridInqYinc(gridID);
+	  double yfirst = gridInqYval(gridID, 0);
+	  double ylast  = gridInqYval(gridID, ysize-1);
+	  double yinc   = gridInqYinc(gridID);
 
           fprintf(stdout, " : points=%d", gridsize);
 	  if ( gridtype == GRID_GAUSSIAN_REDUCED )
@@ -184,20 +187,21 @@ void printGridInfo(int vlistID)
 
 	  fprintf(stdout, "\n");
 
-          if ( gridInqXvals(gridID, NULL) == 0 ) lxcoord = 0;
-          if ( gridInqYvals(gridID, NULL) == 0 ) lycoord = 0;
+          bool lxcoord = true, lycoord = true;
+          if ( gridInqXvals(gridID, NULL) == 0 ) lxcoord = false;
+          if ( gridInqYvals(gridID, NULL) == 0 ) lycoord = false;
 
 	  if ( xsize > 0 && lxcoord )
 	    {
-              xfirst = gridInqXval(gridID, 0);
-              xlast  = gridInqXval(gridID, xsize-1);
-              xinc   = gridInqXinc(gridID);
-              fprintf(stdout, "%33s : %g", xname, xfirst);
+              double xfirst = gridInqXval(gridID, 0);
+              double xlast  = gridInqXval(gridID, xsize-1);
+              double xinc   = gridInqXinc(gridID);
+              fprintf(stdout, "%33s : %.*g", xname, dig, xfirst);
               if ( xsize > 1 )
                 {
-                  fprintf(stdout, " to %g", xlast);
+                  fprintf(stdout, " to %.*g", dig, xlast);
                   if ( IS_NOT_EQUAL(xinc, 0) )
-                    fprintf(stdout, " by %g", xinc);
+                    fprintf(stdout, " by %.*g", dig, xinc);
                 }
               fprintf(stdout, " %s", xunits);
               if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
@@ -206,12 +210,12 @@ void printGridInfo(int vlistID)
 
 	  if ( ysize > 0 && lycoord )
 	    {
-	      fprintf(stdout, "%33s : %g", yname, yfirst);
+	      fprintf(stdout, "%33s : %.*g", yname, dig, yfirst);
 	      if ( ysize > 1 )
                 {
-                  fprintf(stdout, " to %g", ylast);
+                  fprintf(stdout, " to %.*g", dig, ylast);
                   if ( IS_NOT_EQUAL(yinc, 0) && gridtype != GRID_GAUSSIAN && gridtype != GRID_GAUSSIAN_REDUCED )
-                    fprintf(stdout, " by %g", yinc);
+                    fprintf(stdout, " by %.*g", dig, yinc);
                 }
               fprintf(stdout, " %s", yunits);
 	      fprintf(stdout, "\n");
@@ -219,12 +223,11 @@ void printGridInfo(int vlistID)
 
 	  if ( gridIsRotated(gridID) )
 	    {
-	      double lonpole, latpole, angle;
-	      lonpole = gridInqXpole(gridID);
-	      latpole = gridInqYpole(gridID);
-	      angle   = gridInqAngle(gridID);
-	      fprintf(stdout, "%33s : lon=%g  lat=%g", "northpole", lonpole, latpole);
-	      if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, "  angle=%g", angle);
+	      double lonpole = gridInqXpole(gridID);
+	      double latpole = gridInqYpole(gridID);
+	      double angle   = gridInqAngle(gridID);
+	      fprintf(stdout, "%33s : lon=%.*g  lat=%.*g", "northpole", dig, lonpole, dig, latpole);
+	      if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, "  angle=%.*g", dig, angle);
 	      fprintf(stdout, "\n");
 	    }
 
@@ -264,9 +267,8 @@ void printGridInfo(int vlistID)
 	}
       else if ( gridtype == GRID_GME )
 	{
-	  int ni, nd;
-	  ni = gridInqGMEni(gridID);
-	  nd = gridInqGMEnd(gridID);
+	  int ni = gridInqGMEni(gridID);
+	  int nd = gridInqGMEnd(gridID);
 	  fprintf(stdout, " : points=%d  nd=%d  ni=%d\n", gridsize, nd, ni);
 	}
       else if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
@@ -301,20 +303,17 @@ void printGridInfo(int vlistID)
 
 	  if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
 	    {
-	      int i;
-	      double *xvals, *yvals;
-	      double xfirst, xlast, yfirst, ylast;
-	      xvals = (double*) malloc((size_t)gridsize*sizeof(double));
-	      yvals = (double*) malloc((size_t)gridsize*sizeof(double));
+	      double *xvals = (double*) malloc((size_t)gridsize*sizeof(double));
+	      double *yvals = (double*) malloc((size_t)gridsize*sizeof(double));
 
 	      gridInqXvals(gridID, xvals);
 	      gridInqYvals(gridID, yvals);
 
-	      xfirst = xvals[0];
-	      xlast  = xvals[0];
-	      yfirst = yvals[0];
-	      ylast  = yvals[0];
-	      for ( i = 1; i < gridsize; i++ )
+	      double xfirst = xvals[0];
+	      double xlast  = xvals[0];
+	      double yfirst = yvals[0];
+	      double ylast  = yvals[0];
+	      for ( int i = 1; i < gridsize; i++ )
 		{
 		  if ( xvals[i] < xfirst ) xfirst = xvals[i];
 		  if ( xvals[i] > xlast  ) xlast  = xvals[i];
@@ -322,10 +321,10 @@ void printGridInfo(int vlistID)
 		  if ( yvals[i] > ylast  ) ylast  = yvals[i];
 		}
 
-	      fprintf(stdout, "%33s : %g to %g %s", xname, xfirst, xlast, xunits);
+	      fprintf(stdout, "%33s : %.*g to %.*g %s", xname, dig, xfirst, dig, xlast, xunits);
 	      if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
 	      fprintf(stdout, "\n");
-	      fprintf(stdout, "%33s : %g to %g %s\n", yname, yfirst, ylast, yunits);
+	      fprintf(stdout, "%33s : %.*g to %.*g %s\n", yname, dig, yfirst, dig, ylast, yunits);
 
 	      free(xvals);
 	      free(yvals);
@@ -385,19 +384,20 @@ void printGridInfo(int vlistID)
 static
 void printZaxisInfo(int vlistID)
 {
-  int zaxisID, zaxistype, levelsize, levelID;
-  int ltype;
-  double *levels = NULL;
   char zaxisname[CDI_MAX_NAME], zname[CDI_MAX_NAME], zunits[CDI_MAX_NAME];
 
   int nzaxis = vlistNzaxis(vlistID);
-  for ( int index = 0; index < nzaxis; index++)
+  for ( int index = 0; index < nzaxis; index++ )
     {
-      double zfirst = 0, zlast = 0, zinc = 0;
-      zaxisID   = vlistZaxis(vlistID, index);
-      zaxistype = zaxisInqType(zaxisID);
-      ltype     = zaxisInqLtype(zaxisID);
-      levelsize = zaxisInqSize(zaxisID);
+      double zinc = 0;
+      int zaxisID   = vlistZaxis(vlistID, index);
+      int zaxistype = zaxisInqType(zaxisID);
+      int ltype     = zaxisInqLtype(zaxisID);
+      int levelsize = zaxisInqSize(zaxisID);
+      int prec      = zaxisInqPrec(zaxisID);
+
+      int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
+
       zaxisName(zaxistype, zaxisname);
       zaxisInqName(zaxisID, zname);
       zaxisInqUnits(zaxisID, zunits);
@@ -411,15 +411,16 @@ void printZaxisInfo(int vlistID)
       fprintf(stdout, " levels=%d", levelsize);
       fprintf(stdout, "\n");
 
-      levels = (double*) malloc((size_t)levelsize*sizeof(double));
+      double *levels = (double*) malloc((size_t)levelsize*sizeof(double));
       zaxisInqLevels(zaxisID, levels);
 
       if ( !(zaxistype == ZAXIS_SURFACE && levelsize == 1 && !(fabs(levels[0]) > 0)) )
         {
-          zfirst = levels[0];
-          zlast  = levels[levelsize-1];
+          double zfirst = levels[0];
+          double zlast  = levels[levelsize-1];
           if ( levelsize > 2 )
             {
+              int levelID;
               zinc = (levels[levelsize-1] - levels[0]) / (levelsize-1);
               for ( levelID = 2; levelID < levelsize; ++levelID )
                 if ( fabs(fabs(levels[levelID] - levels[levelID-1]) - zinc) > 0.001*zinc ) break;
@@ -427,12 +428,12 @@ void printZaxisInfo(int vlistID)
               if ( levelID < levelsize ) zinc = 0;
             }
 
-          fprintf(stdout, "%33s : %g", zname, zfirst);
+          fprintf(stdout, "%33s : %.*g", zname, dig, zfirst);
           if ( levelsize > 1 )
             {
-              fprintf(stdout, " to %g", zlast);
+              fprintf(stdout, " to %.*g", dig, zlast);
               if ( IS_NOT_EQUAL(zinc, 0) )
-                fprintf(stdout, " by %g", zinc);
+                fprintf(stdout, " by %.*g", dig, zinc);
             }
           fprintf(stdout, " %s", zunits);
           fprintf(stdout, "\n");
@@ -447,14 +448,14 @@ void printZaxisInfo(int vlistID)
 
           level1 = zaxisInqLbound(zaxisID, 0);
           level2 = zaxisInqUbound(zaxisID, 0);
-          fprintf(stdout, "%.9g-%.9g", level1, level2);
+          fprintf(stdout, "%.*g-%.*g", dig, level1, dig, level2);
           if ( levelsize > 1 )
             {
               level1 = zaxisInqLbound(zaxisID, levelsize-1);
               level2 = zaxisInqUbound(zaxisID, levelsize-1);
-              fprintf(stdout, " to %.9g-%.9g", level1, level2);
+              fprintf(stdout, " to %.*g-%.*g", dig, level1, dig, level2);
               if ( IS_NOT_EQUAL(zinc, 0) )
-                fprintf(stdout, " by %g", zinc);
+                fprintf(stdout, " by %.*g", dig, zinc);
             }
           fprintf(stdout, " %s", zunits);
           fprintf(stdout, "\n");
@@ -566,7 +567,6 @@ static
 void printTimesteps(int streamID, int taxisID, int verbose)
 {
   int nrecs;
-  int vdate, vtime;
   struct datetime {
     int vdate;
     int vtime;
@@ -585,10 +585,19 @@ void printTimesteps(int streamID, int taxisID, int verbose)
   int nfact = 1;
   int tsID = 0;
 
+#ifdef CDO
+  dtlist_type *dtlist = dtlist_new();
+#endif
   while ( (nrecs = streamInqTimestep(streamID, tsID)) )
     {
-      vdate = taxisInqVdate(taxisID);
-      vtime = taxisInqVtime(taxisID);
+#ifdef CDO
+      dtlist_taxisInqTimestep(dtlist, taxisID, 0);
+      int vdate = dtlist_get_vdate(dtlist, 0);
+      int vtime = dtlist_get_vtime(dtlist, 0);
+#else
+      int vdate = taxisInqVdate(taxisID);
+      int vtime = taxisInqVtime(taxisID);
+#endif
 
       if ( verbose || tsID < NUM_TIMESTEP )
 	{
@@ -616,6 +625,9 @@ void printTimesteps(int streamID, int taxisID, int verbose)
       tsID++;
     }
 
+#ifdef CDO
+  dtlist_delete(dtlist);
+#endif
   if ( nvdatetime )
     {
       fprintf(stdout, "\n");
@@ -630,8 +642,8 @@ void printTimesteps(int streamID, int taxisID, int verbose)
         }
       for ( int i = toff; i < nvdatetime; ++i )
 	{
-	  vdate = next_vdatetime->vdate;
-	  vtime = next_vdatetime->vtime;
+	  int vdate = next_vdatetime->vdate;
+	  int vtime = next_vdatetime->vtime;
 	  ntimeout = printDateTime(ntimeout, vdate, vtime);
 	  next_vdatetime = next_vdatetime->next;
 	}
diff --git a/libcdi/cdi.settings.in b/libcdi/cdi.settings.in
index cc0877f..a53f5fc 100644
--- a/libcdi/cdi.settings.in
+++ b/libcdi/cdi.settings.in
@@ -36,18 +36,10 @@
         "fclibs"   : "@MPI_FC_LIB@",
         "fcflags"  : "@MPI_FC_INCLUDE@"
       },
-      "zlib"     : {
-        "lib"      : "@ZLIB_LIBS@",
-        "include"  : "@ZLIB_INCLUDE@"
-      },
       "szlib"    : {
         "lib"      : "@SZLIB_LIBS@",
         "include"  : "@SZLIB_INCLUDE@"
       },
-      "hdf5"     : {
-        "lib"      : "@HDF5_LIBS@",
-        "include"  : "@HDF5_INCLUDE@"
-      },
       "netcdf"   : {
         "lib"      : "@NETCDF_LIBS@",
         "include"  : "@NETCDF_INCLUDE@"
diff --git a/libcdi/config/config.guess b/libcdi/config/config.guess
index 7f53479..d5d667d 100755
--- a/libcdi/config/config.guess
+++ b/libcdi/config/config.guess
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2013 Free Software Foundation, Inc.
+#   Copyright 1992-2016 Free Software Foundation, Inc.
 
-timestamp='2014-08-20'
+timestamp='2016-03-24'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -24,12 +24,12 @@ timestamp='2014-08-20'
 # program.  This Exception is an additional permission under section 7
 # of the GNU General Public License, version 3 ("GPLv3").
 #
-# Originally written by Per Bothner.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
 # You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 #
-# Please send patches with a ChangeLog entry to config-patches at gnu.org.
+# Please send patches to <config-patches at gnu.org>.
 
 
 me=`echo "$0" | sed -e 's,.*/,,'`
@@ -50,7 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2013 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -149,8 +149,7 @@ Linux|GNU|GNU/*)
 	LIBC=gnu
 	#endif
 	EOF
-        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null \
-          | sed -n 's/^LIBC *= */LIBC=/p'`
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
 	;;
 esac
 
@@ -169,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# Note: NetBSD doesn't particularly care about the vendor
 	# portion of the name.  We always set it to "unknown".
 	sysctl="sysctl -n hw.machine_arch"
-	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
-	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	    /sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || \
+	    echo unknown)`
 	case "${UNAME_MACHINE_ARCH}" in
 	    armeb) machine=armeb-unknown ;;
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
 	    sh5el) machine=sh5le-unknown ;;
+	    earmv*)
+		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+		machine=${arch}${endian}-unknown
+		;;
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
 	# to ELF recently, or will in the future.
 	case "${UNAME_MACHINE_ARCH}" in
-	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
 		eval $set_cc_for_build
 		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
 			| grep -q __ELF__
@@ -198,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		os=netbsd
 		;;
 	esac
+	# Determine ABI tags.
+	case "${UNAME_MACHINE_ARCH}" in
+	    earm*)
+		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+		;;
+	esac
 	# The OS release
 	# Debian GNU/NetBSD machines have a different userland, and
 	# thus, need a distinct triplet. However, they do not need
@@ -208,13 +221,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		release='-gnu'
 		;;
 	    *)
-		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
 		;;
 	esac
 	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
 	# contains redundant information, the shorter form:
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-	echo "${machine}-${os}${release}"
+	echo "${machine}-${os}${release}${abi}"
 	exit ;;
     *:Bitrig:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
@@ -224,6 +237,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
 	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
 	exit ;;
+    *:LibertyBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+	exit ;;
     *:ekkoBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
 	exit ;;
@@ -236,6 +253,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:MirBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
 	exit ;;
+    *:Sortix:*:*)
+	echo ${UNAME_MACHINE}-unknown-sortix
+	exit ;;
     alpha:OSF1:*:*)
 	case $UNAME_RELEASE in
 	*4.0)
@@ -252,42 +272,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
 	case "$ALPHA_CPU_TYPE" in
 	    "EV4 (21064)")
-		UNAME_MACHINE="alpha" ;;
+		UNAME_MACHINE=alpha ;;
 	    "EV4.5 (21064)")
-		UNAME_MACHINE="alpha" ;;
+		UNAME_MACHINE=alpha ;;
 	    "LCA4 (21066/21068)")
-		UNAME_MACHINE="alpha" ;;
+		UNAME_MACHINE=alpha ;;
 	    "EV5 (21164)")
-		UNAME_MACHINE="alphaev5" ;;
+		UNAME_MACHINE=alphaev5 ;;
 	    "EV5.6 (21164A)")
-		UNAME_MACHINE="alphaev56" ;;
+		UNAME_MACHINE=alphaev56 ;;
 	    "EV5.6 (21164PC)")
-		UNAME_MACHINE="alphapca56" ;;
+		UNAME_MACHINE=alphapca56 ;;
 	    "EV5.7 (21164PC)")
-		UNAME_MACHINE="alphapca57" ;;
+		UNAME_MACHINE=alphapca57 ;;
 	    "EV6 (21264)")
-		UNAME_MACHINE="alphaev6" ;;
+		UNAME_MACHINE=alphaev6 ;;
 	    "EV6.7 (21264A)")
-		UNAME_MACHINE="alphaev67" ;;
+		UNAME_MACHINE=alphaev67 ;;
 	    "EV6.8CB (21264C)")
-		UNAME_MACHINE="alphaev68" ;;
+		UNAME_MACHINE=alphaev68 ;;
 	    "EV6.8AL (21264B)")
-		UNAME_MACHINE="alphaev68" ;;
+		UNAME_MACHINE=alphaev68 ;;
 	    "EV6.8CX (21264D)")
-		UNAME_MACHINE="alphaev68" ;;
+		UNAME_MACHINE=alphaev68 ;;
 	    "EV6.9A (21264/EV69A)")
-		UNAME_MACHINE="alphaev69" ;;
+		UNAME_MACHINE=alphaev69 ;;
 	    "EV7 (21364)")
-		UNAME_MACHINE="alphaev7" ;;
+		UNAME_MACHINE=alphaev7 ;;
 	    "EV7.9 (21364A)")
-		UNAME_MACHINE="alphaev79" ;;
+		UNAME_MACHINE=alphaev79 ;;
 	esac
 	# A Pn.n version is a patched version.
 	# A Vn.n version is a released version.
 	# A Tn.n version is a released field test version.
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
-	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
 	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
 	exitcode=$?
 	trap '' 0
@@ -360,16 +380,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	exit ;;
     i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
 	eval $set_cc_for_build
-	SUN_ARCH="i386"
+	SUN_ARCH=i386
 	# If there is a compiler, see if it is configured for 64-bit objects.
 	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
 	# This test works for both compilers.
-	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
 	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
 		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
 		grep IS_64BIT_ARCH >/dev/null
 	    then
-		SUN_ARCH="x86_64"
+		SUN_ARCH=x86_64
 	    fi
 	fi
 	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
@@ -394,7 +414,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	exit ;;
     sun*:*:4.2BSD:*)
 	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
-	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
 	case "`/bin/arch`" in
 	    sun3)
 		echo m68k-sun-sunos${UNAME_RELEASE}
@@ -580,8 +600,9 @@ EOF
 	else
 		IBM_ARCH=powerpc
 	fi
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
+	if [ -x /usr/bin/lslpp ] ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
 	else
 		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
 	fi
@@ -618,13 +639,13 @@ EOF
 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
 		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
 		    case "${sc_cpu_version}" in
-		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
 		      532)                      # CPU_PA_RISC2_0
 			case "${sc_kernel_bits}" in
-			  32) HP_ARCH="hppa2.0n" ;;
-			  64) HP_ARCH="hppa2.0w" ;;
-			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+			  32) HP_ARCH=hppa2.0n ;;
+			  64) HP_ARCH=hppa2.0w ;;
+			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
 			esac ;;
 		    esac
 		fi
@@ -667,7 +688,7 @@ EOF
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
 		fi ;;
 	esac
-	if [ ${HP_ARCH} = "hppa2.0w" ]
+	if [ ${HP_ARCH} = hppa2.0w ]
 	then
 	    eval $set_cc_for_build
 
@@ -683,9 +704,9 @@ EOF
 	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
 		grep -q __LP64__
 	    then
-		HP_ARCH="hppa2.0w"
+		HP_ARCH=hppa2.0w
 	    else
-		HP_ARCH="hppa64"
+		HP_ARCH=hppa64
 	    fi
 	fi
 	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
@@ -790,14 +811,14 @@ EOF
 	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
-	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
 	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
 	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     5000:UNIX_System_V:4.*:*)
-	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
 	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
@@ -827,7 +848,7 @@ EOF
     *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
-    i*:MSYS*:*)
+    *:MSYS*:*)
 	echo ${UNAME_MACHINE}-pc-msys
 	exit ;;
     i*:windows32*:*)
@@ -902,7 +923,7 @@ EOF
 	  EV68*) UNAME_MACHINE=alphaev68 ;;
 	esac
 	objdump --private-headers /bin/sh | grep -q ld.so.1
-	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
 	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     arc:Linux:*:* | arceb:Linux:*:*)
@@ -933,6 +954,9 @@ EOF
     crisv32:Linux:*:*)
 	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
 	exit ;;
+    e2k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
     frv:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
@@ -945,6 +969,9 @@ EOF
     ia64:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
+    k1om:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
     m32r*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
@@ -970,10 +997,10 @@ EOF
 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
 	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
 	;;
-    or1k:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-${LIBC}
 	exit ;;
-    or32:Linux:*:*)
+    or32:Linux:*:* | or1k*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     padre:Linux:*:*)
@@ -1021,7 +1048,7 @@ EOF
 	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
 	exit ;;
     x86_64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
 	exit ;;
     xtensa*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
@@ -1100,7 +1127,7 @@ EOF
 	# uname -m prints for DJGPP always 'pc', but it prints nothing about
 	# the processor, so we play safe by assuming i586.
 	# Note: whatever this is, it MUST be the same as what config.sub
-	# prints for the "djgpp" host, or else GDB configury will decide that
+	# prints for the "djgpp" host, or else GDB configure will decide that
 	# this is a cross-build.
 	echo i586-pc-msdosdjgpp
 	exit ;;
@@ -1249,6 +1276,9 @@ EOF
     SX-8R:SUPER-UX:*:*)
 	echo sx8r-nec-superux${UNAME_RELEASE}
 	exit ;;
+    SX-ACE:SUPER-UX:*:*)
+	echo sxace-nec-superux${UNAME_RELEASE}
+	exit ;;
     Power*:Rhapsody:*:*)
 	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 	exit ;;
@@ -1261,22 +1291,32 @@ EOF
 	if test "$UNAME_PROCESSOR" = unknown ; then
 	    UNAME_PROCESSOR=powerpc
 	fi
-	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
-	    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-		grep IS_64BIT_ARCH >/dev/null
-	    then
-		case $UNAME_PROCESSOR in
-		    i386) UNAME_PROCESSOR=x86_64 ;;
-		    powerpc) UNAME_PROCESSOR=powerpc64 ;;
-		esac
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
 	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
 	fi
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 	exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
 	UNAME_PROCESSOR=`uname -p`
-	if test "$UNAME_PROCESSOR" = "x86"; then
+	if test "$UNAME_PROCESSOR" = x86; then
 		UNAME_PROCESSOR=i386
 		UNAME_MACHINE=pc
 	fi
@@ -1307,7 +1347,7 @@ EOF
 	# "uname -m" is not consistent, so use $cputype instead. 386
 	# is converted to i386 for consistency with other x86
 	# operating systems.
-	if test "$cputype" = "386"; then
+	if test "$cputype" = 386; then
 	    UNAME_MACHINE=i386
 	else
 	    UNAME_MACHINE="$cputype"
@@ -1360,155 +1400,10 @@ EOF
     x86_64:VMkernel:*:*)
 	echo ${UNAME_MACHINE}-unknown-esx
 	exit ;;
-esac
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-	"4"
-#else
-	""
-#endif
-	); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-	printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-	printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-#  include <sys/param.h>
-#  if defined (BSD)
-#   if BSD == 43
-      printf ("vax-dec-bsd4.3\n"); exit (0);
-#   else
-#    if BSD == 199006
-      printf ("vax-dec-bsd4.3reno\n"); exit (0);
-#    else
-      printf ("vax-dec-bsd\n"); exit (0);
-#    endif
-#   endif
-#  else
-    printf ("vax-dec-bsd\n"); exit (0);
-#  endif
-# else
-    printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
-	{ echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-	echo c1-convex-bsd
+    amd64:Isilon\ OneFS:*:*)
+	echo x86_64-unknown-onefs
 	exit ;;
-    c2*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit ;;
-    c34*)
-	echo c34-convex-bsd
-	exit ;;
-    c38*)
-	echo c38-convex-bsd
-	exit ;;
-    c4*)
-	echo c4-convex-bsd
-	exit ;;
-    esac
-fi
+esac
 
 cat >&2 <<EOF
 $0: unable to guess system type
@@ -1517,9 +1412,9 @@ This script, last modified $timestamp, has failed to recognize
 the operating system you are using. It is advised that you
 download the most up to date version of the config scripts from
 
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 and
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
 If the version you run ($0) is already up to date, please
 send the following data and any information you think might be
diff --git a/libcdi/config/config.sub b/libcdi/config/config.sub
index 8b612ab..6223dde 100755
--- a/libcdi/config/config.sub
+++ b/libcdi/config/config.sub
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2013 Free Software Foundation, Inc.
+#   Copyright 1992-2016 Free Software Foundation, Inc.
 
-timestamp='2013-04-24'
+timestamp='2016-01-01'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ timestamp='2013-04-24'
 # of the GNU General Public License, version 3 ("GPLv3").
 
 
-# Please send patches with a ChangeLog entry to config-patches at gnu.org.
+# Please send patches to <config-patches at gnu.org>.
 #
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
@@ -33,7 +33,7 @@ timestamp='2013-04-24'
 # Otherwise, we print the canonical config type on stdout and succeed.
 
 # You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
@@ -53,8 +53,7 @@ timestamp='2013-04-24'
 me=`echo "$0" | sed -e 's,.*/,,'`
 
 usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
-       $0 [OPTION] ALIAS
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
 
 Canonicalize a configuration name.
 
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches at gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2013 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -117,7 +116,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
   nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
   linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
-  knetbsd*-gnu* | netbsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
   kopensolaris*-gnu* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
@@ -255,16 +254,18 @@ case $basic_machine in
 	| arc | arceb \
 	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
 	| avr | avr32 \
+	| ba \
 	| be32 | be64 \
 	| bfin \
-	| c4x | clipper \
+	| c4x | c8051 | clipper \
 	| d10v | d30v | dlx | dsp16xx \
-	| epiphany \
-	| fido | fr30 | frv \
+	| e2k | epiphany \
+	| fido | fr30 | frv | ft32 \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 	| hexagon \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
+	| k1om \
 	| le32 | le64 \
 	| lm32 \
 	| m32c | m32r | m32rle | m68000 | m68k | m88k \
@@ -282,8 +283,10 @@ case $basic_machine in
 	| mips64vr5900 | mips64vr5900el \
 	| mipsisa32 | mipsisa32el \
 	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
 	| mipsisa64 | mipsisa64el \
 	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
 	| mipsisa64sb1 | mipsisa64sb1el \
 	| mipsisa64sr71k | mipsisa64sr71kel \
 	| mipsr5900 | mipsr5900el \
@@ -295,14 +298,14 @@ case $basic_machine in
 	| nds32 | nds32le | nds32be \
 	| nios | nios2 | nios2eb | nios2el \
 	| ns16k | ns32k \
-	| open8 \
-	| or1k | or32 \
+	| open8 | or1k | or1knd | or32 \
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle \
 	| pyramid \
+	| riscv32 | riscv64 \
 	| rl78 | rx \
 	| score \
-	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
@@ -310,6 +313,7 @@ case $basic_machine in
 	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
 	| ubicom32 \
 	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| visium \
 	| we32k \
 	| x86 | xc16x | xstormy16 | xtensa \
 	| z8k | z80)
@@ -324,7 +328,10 @@ case $basic_machine in
 	c6x)
 		basic_machine=tic6x-unknown
 		;;
-	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
+	leon|leon[3-9])
+		basic_machine=sparc-$basic_machine
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
 		basic_machine=$basic_machine-unknown
 		os=-none
 		;;
@@ -369,18 +376,20 @@ case $basic_machine in
 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
+	| ba-* \
 	| be32-* | be64-* \
 	| bfin-* | bs2000-* \
 	| c[123]* | c30-* | [cjt]90-* | c4x-* \
-	| clipper-* | craynv-* | cydra-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
-	| elxsi-* \
+	| e2k-* | elxsi-* \
 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 	| hexagon-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
+	| k1om-* \
 	| le32-* | le64-* \
 	| lm32-* \
 	| m32c-* | m32r-* | m32rle-* \
@@ -400,8 +409,10 @@ case $basic_machine in
 	| mips64vr5900-* | mips64vr5900el-* \
 	| mipsisa32-* | mipsisa32el-* \
 	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
 	| mipsisa64-* | mipsisa64el-* \
 	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
 	| mipsr5900-* | mipsr5900el-* \
@@ -413,16 +424,18 @@ case $basic_machine in
 	| nios-* | nios2-* | nios2eb-* | nios2el-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
 	| open8-* \
+	| or1k*-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
 	| pyramid-* \
+	| riscv32-* | riscv64-* \
 	| rl78-* | romp-* | rs6000-* | rx-* \
 	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
 	| tahoe-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
 	| tile*-* \
@@ -430,6 +443,7 @@ case $basic_machine in
 	| ubicom32-* \
 	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
 	| vax-* \
+	| visium-* \
 	| we32k-* \
 	| x86-* | x86_64-* | xc16x-* | xps100-* \
 	| xstormy16-* | xtensa*-* \
@@ -506,6 +520,9 @@ case $basic_machine in
 		basic_machine=i386-pc
 		os=-aros
 		;;
+	asmjs)
+		basic_machine=asmjs-unknown
+		;;
 	aux)
 		basic_machine=m68k-apple
 		os=-aux
@@ -767,6 +784,9 @@ case $basic_machine in
 		basic_machine=m68k-isi
 		os=-sysv
 		;;
+	leon-*|leon[3-9]-*)
+		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+		;;
 	m68knommu)
 		basic_machine=m68k-unknown
 		os=-linux
@@ -794,7 +814,7 @@ case $basic_machine in
 		os=-mingw64
 		;;
 	mingw32)
-		basic_machine=i386-pc
+		basic_machine=i686-pc
 		os=-mingw32
 		;;
 	mingw32ce)
@@ -822,6 +842,10 @@ case $basic_machine in
 		basic_machine=powerpc-unknown
 		os=-morphos
 		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
 	msdos)
 		basic_machine=i386-pc
 		os=-msdos
@@ -830,7 +854,7 @@ case $basic_machine in
 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
 		;;
 	msys)
-		basic_machine=i386-pc
+		basic_machine=i686-pc
 		os=-msys
 		;;
 	mvs)
@@ -1354,11 +1378,11 @@ case $os in
 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
 	      | -sym* | -kopensolaris* | -plan9* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* | -aros* \
+	      | -aos* | -aros* | -cloudabi* | -sortix* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -bitrig* | -openbsd* | -solidbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
@@ -1367,14 +1391,15 @@ case $os in
 	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
 	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
 	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
-	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+	      | -onefs* | -tirtos*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1546,6 +1571,9 @@ case $basic_machine in
 	c4x-* | tic4x-*)
 		os=-coff
 		;;
+	c8051-*)
+		os=-elf
+		;;
 	hexagon-*)
 		os=-elf
 		;;
@@ -1589,9 +1617,6 @@ case $basic_machine in
 	mips*-*)
 		os=-elf
 		;;
-	or1k-*)
-		os=-elf
-		;;
 	or32-*)
 		os=-coff
 		;;
diff --git a/libcdi/config/default b/libcdi/config/default
index 2117f4e..3b3a495 100755
--- a/libcdi/config/default
+++ b/libcdi/config/default
@@ -2,6 +2,12 @@
 #
 # default configuration options and compiler flags for different hosts
 #
+#
+CONFPATH=`echo $0 | cut -c 1-6`
+if [ "$CONFPATH" != "../../" ] ; then
+  CONFPATH='./'
+fi
+#
 if test -z "$1" ; then
   HOSTNAME=`hostname`
 else
@@ -13,19 +19,18 @@ set -x
 case "${HOSTNAME}" in
 # i386-apple-darwin10
     icc)
-	./configure --prefix=$HOME/local \
+	${CONFPATH}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.12.3 \
                     --with-netcdf=$HOME/local \
                     --with-szlib=$HOME/local \
 	            CC=icc CFLAGS="-g -D_REENTRANT -Wall -Wwrite-strings -O3 -march=native -fp-model source"
 	;;
     bailung*|d133*|d134*)
-	./configure --prefix=$HOME/local \
+	${CONFPATH}configure --prefix=$HOME/local \
                     --enable-maintainer-mode \
                     --enable-iso-c-interface \
                     --enable-swig \
@@ -36,22 +41,18 @@ case "${HOSTNAME}" in
 	            CC=gcc CFLAGS="-g -pipe -D_REENTRANT -Wall -Wwrite-strings -W -Wfloat-equal -pedantic -O3 -march=native"
 	;;
     cinglung*|feilung*|wanglung*)
-	./configure --prefix=$HOME/local \
+	${CONFPATH}configure --prefix=$HOME/local \
                     --enable-shared \
                     --enable-maintainer-mode \
                     --enable-swig \
                     --enable-python \
-                    --with-jasper=/opt/local \
-                    --with-openjpeg=/opt/local \
-                    --with-libpng=/opt/local \
                     --with-grib_api=/opt/local \
                     --with-netcdf=/opt/local \
-                    --with-hdf5=/opt/local \
                     --with-szlib=/opt/local \
 	            CC=gcc CFLAGS="-g -pipe -D_REENTRANT -Wall -W -Wfloat-equal -pedantic -O2"
 	;;
     hama*)
-	./configure --prefix=$HOME/local \
+	${CONFPATH}configure --prefix=$HOME/local \
                     --enable-maintainer-mode \
                     --enable-iso-c-interface \
                     --enable-swig \
@@ -60,61 +61,63 @@ case "${HOSTNAME}" in
                     --with-netcdf=$HOME/local \
 	            CC=gcc CFLAGS="-g -pipe -D_REENTRANT -Wall -Wwrite-strings -W -Wfloat-equal -pedantic -O3"
 	;;
+# x86_64-squeeze-x64-linux
+    thunder*)
+        ${CONFPATH}configure --with-grib_api=/sw/squeeze-x64/grib_api-1.13.0-static-gccsys \
+                    --with-netcdf=/sw/squeeze-x64/netcdf-4.2-static \
+                    --disable-cf-interface \
+	            CC=gcc CFLAGS="-g -Wall -O3" 
+	;;
 # ia64-nec-linux
     ds*)
-	./configure --prefix=$HOME/local \
+	${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"
 	;;
 # i686-linux
     etch-ia32 | gata)
-	./configure --prefix=$HOME/local/etch-ia32 \
+	${CONFPATH}configure --prefix=$HOME/local/etch-ia32 \
                     --enable-maintainer-mode \
                     --enable-all-static \
                     --enable-swig \
                     --enable-python \
-                    --with-jasper=/sw/etch-ia32/jasper-1.900.1 \
                     --with-grib_api=$HOME/local/etch-ia32/grib_api-1.9.8 \
 	            --with-netcdf=/sw/etch-ia32/netcdf-4.0.1 \
-	            --with-hdf5=/sw/etch-ia32/hdf5-1.8.2 \
-                    --with-zlib=/sw/etch-ia32/zlib-1.2.3 \
                     --with-szlib=$HOME/local/etch-ia32 \
 	            CC=gcc CFLAGS="-g -O2 -Wall -W -Wfloat-equal -pedantic"
 	;;
     thingol)
-      ./configure --prefix=`pwd`/build \
+      ${CONFPATH}configure --prefix=`pwd`/build \
 	            --with-netcdf=$HOME/builds/libs4cdo \
-	              --with-hdf5=$HOME/builds/libs4cdo \
                      --with-szlib=$HOME/builds/libs4cdo \
                   --with-grib_api=$HOME/builds/libs4cdo \
-                    --with-jasper=$HOME/builds/libs4cdo \
                       --with-pic --enable-swig --enable-ruby --enable-python \
                       CC=gcc CFLAGS="-g -O2 -Wall" LIBS=-lopenjpeg
 	;;
 # sparc-sun-solaris2.9
     executor | yang | yin)
-	./configure --prefix=$HOME/local/SUN64 \
+	${CONFPATH}configure --prefix=$HOME/local/SUN64 \
                     --with-netcdf=/scratch/small/m214/m214089/local/SunOS64 \
                     --with-szlib=$HOME/local/solaris10 \
                     CC=cc CFLAGS="-g -mt -xO3 -xtarget=native -m64"
 	;;
 # sx6-nec-superux12.2
     cs*)
-	./configure --prefix=$HOME/local \
+	${CONFPATH}configure --prefix=$HOME/local \
          	    --with-netcdf=/pool/netcdf/netcdf-3.6.0-p1 \
 		    CC=c++ \
                     CFLAGS="-O -Onooverlap,restrict=all -pvctl,fullmsg,noassume,loopcnt=1000000"
 	;;
     sx6)
-	./configure --host=sx6 --prefix=$HOME/local \
+	${CONFPATH}configure --host=sx6 --prefix=$HOME/local \
                     --with-netcdf=/pool/SX-6/netcdf/netcdf-3.6.0-p1 \
 		    CC=sxc++ AR=sxar RANLIB=ls \
                     CFLAGS="-O -Onooverlap,restrict=all -pvctl,fullmsg,noassume,loopcnt=1000000"
 	;;
     lxe0*)
         echo 'Please choose compiler modules! Checkout with "module av"!'
-        ./configure --prefix=$(pwd)/build-SX  --host=sx9-nec-superux \
+        ${CONFPATH}configure --prefix=$(pwd)/build-SX  --host=sx9-nec-superux \
               --with-netcdf=/usr/local/pkg-sx9 \
               --with-grib_api=/usr/local/pkg-sx9/grib_api   CC=sxc++ FC=sxf90 \
               LD=/SX/opt/crosskit/inst/bin/sxld AR=/SX/opt/crosskit/inst/bin/sxar \
@@ -122,22 +125,20 @@ case "${HOSTNAME}" in
 	;;
 # mips-sgi-irix6.5
     ecgate1)
-	./configure --prefix=$HOME/local \
+	${CONFPATH}configure --prefix=$HOME/local \
  	            --with-netcdf=/home/ms/spdekplb/hmk/include,/home/ms/spdekplb/hmk/lib64 \
 	            CC=cc CFLAGS="-O -n32"
 	;;
 # 5000-fujitsu-uxpv4.1_ES
     vpp5)
-	./configure --prefix=$HOME \
+	${CONFPATH}configure --prefix=$HOME \
 	            CC=vcc CFLAGS="-O -Wv,-m3 -K4"
 	;;
 # powerpc-ibm-aix6.1.0.0
     blizzard*)
         CONFIG_SHELL=/bin/bash /bin/bash \
-                    ./configure --prefix=$HOME/local \
+                    ${CONFPATH}configure --prefix=$HOME/local \
                     --with-netcdf=/sw/aix61/netcdf-4.2 \
-                    --with-hdf5=/sw/aix61/hdf5-1.8.8-threadsafe \
-                    --with-zlib=/sw/aix61/zlib-1.2.6 \
                     --with-szlib=/sw/aix61/szip-2.1-threadsafe \
                     AR="ar -X 64" LDFLAGS="-brtl" FC=xlf2003_r CC=xlc_r \
                     CFLAGS="-g -O3 -qhot -q64 -qarch=auto -qtune=auto -qlistfmt=html=transforms -DHAVE_MMAP" \
diff --git a/libcdi/configure b/libcdi/configure
index ff3c62a..b3db107 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.7.1.
+# Generated by GNU Autoconf 2.68 for cdi 1.7.2.
 #
 # Report bugs to <http://mpimet.mpg.de/cdi>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='cdi'
 PACKAGE_TARNAME='cdi'
-PACKAGE_VERSION='1.7.1'
-PACKAGE_STRING='cdi 1.7.1'
+PACKAGE_VERSION='1.7.2'
+PACKAGE_STRING='cdi 1.7.2'
 PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdi'
 PACKAGE_URL=''
 
@@ -695,17 +695,13 @@ JASPER_LIBS
 NETCDF_LIBS
 NETCDF_INCLUDE
 NETCDF_ROOT
+ENABLE_NC4HDF5
 ENABLE_NC4
 ENABLE_NC2
 ENABLE_NETCDF
 NC_CONFIG
-HDF5_LIBS
-HDF5_INCLUDE
-HDF5_ROOT
 SZLIB_LIBS
 SZLIB_INCLUDE
-ZLIB_LIBS
-ZLIB_INCLUDE
 THREADS_LIBS
 THREADS_INCLUDE
 PTHREAD_CFLAGS
@@ -864,9 +860,7 @@ with_sysroot
 enable_libtool_lock
 enable_largefile
 with_threads
-with_zlib
 with_szlib
-with_hdf5
 with_netcdf
 with_jasper
 with_openjpeg
@@ -1473,7 +1467,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures cdi 1.7.1 to adapt to many kinds of systems.
+\`configure' configures cdi 1.7.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1543,7 +1537,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of cdi 1.7.1:";;
+     short | recursive ) echo "Configuration of cdi 1.7.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1593,17 +1587,11 @@ Optional Packages:
                         (or the compiler's sysroot if not specified).
   --with-threads=<yes/no/directory>
                           Compile + link for multithreading [default=yes]
-  --with-zlib=<yes|no|directory> (default=yes)
-                          location of ZLIB compression library (lib and
-                          include subdirs), nec. for HDF5/NETCDF4
   --with-szlib=<yes|no|directory> (default=no)
                           location of szlib library, optional for GRIB1 and
                           NETCDF4 compression
-  --with-hdf5=<yes|no|directory> (default=no)
-                          location of hdf5 library, NETCDF4 requires hdf5 high
-                          level interface
   --with-netcdf=<yes|no|directory> (default=no)
-                          location of netcdf library (lib and include subdirs)
+                          location of NetCDF library (lib and include subdirs)
   --with-jasper=<directory>
                           Specify location of JASPER library. You must specify
                           its location if GRIB_API was built with JASPER.
@@ -1752,7 +1740,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-cdi configure 1.7.1
+cdi configure 1.7.2
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2597,7 +2585,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by cdi $as_me 1.7.1, which was
+It was created by cdi $as_me 1.7.2, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3549,7 +3537,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='cdi'
- VERSION='1.7.1'
+ VERSION='1.7.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -23418,7 +23406,7 @@ Usage: $0 [OPTIONS]
 Report bugs to <bug-libtool at gnu.org>."
 
 lt_cl_version="\
-cdi config.lt 1.7.1
+cdi config.lt 1.7.2
 configured by $0, generated by GNU Autoconf 2.68.
 
 Copyright (C) 2011 Free Software Foundation, Inc.
@@ -26867,248 +26855,7 @@ esac
 
 
 #  ----------------------------------------------------------------------
-#  Link application to ZLIB library, needed for netcdf
-ZLIB_INCLUDE=''
-ZLIB_LIBS=''
-
-# Check whether --with-zlib was given.
-if test "${with_zlib+set}" = set; then :
-  withval=$with_zlib; case "$with_zlib" in #(
-  no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB library" >&5
-$as_echo_n "checking for ZLIB library... " >&6; }
-                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; } ;; #(
-  yes) :
-    for ac_header in zlib.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_zlib_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_ZLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
-$as_echo_n "checking for library containing deflate... " >&6; }
-if ${ac_cv_search_deflate+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' z; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_deflate=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_deflate+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_deflate+:} false; then :
-
-else
-  ac_cv_search_deflate=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
-$as_echo "$ac_cv_search_deflate" >&6; }
-ac_res=$ac_cv_search_deflate
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
-
-fi
-
-                            ZLIB_LIBS=" -lz" ;; #(
-  *) :
-    ZLIB_ROOT=$with_zlib
-                          LDFLAGS="-L$ZLIB_ROOT/lib $LDFLAGS"
-                          CPPFLAGS="-I$ZLIB_ROOT/include $CPPFLAGS"
-                          for ac_header in zlib.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_zlib_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_ZLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-                          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
-$as_echo_n "checking for library containing deflate... " >&6; }
-if ${ac_cv_search_deflate+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' z; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_deflate=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_deflate+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_deflate+:} false; then :
-
-else
-  ac_cv_search_deflate=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
-$as_echo "$ac_cv_search_deflate" >&6; }
-ac_res=$ac_cv_search_deflate
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
-
-fi
-
-                          ZLIB_INCLUDE=" -I$ZLIB_ROOT/include"
-                          ZLIB_LIBS=" -L$ZLIB_ROOT/lib -lz" ;; #(
-  *) :
-     ;;
-esac
-else
-  for ac_header in zlib.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
-if test "x$ac_cv_header_zlib_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_ZLIB_H 1
-_ACEOF
-
-fi
-
-done
-
-                      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
-$as_echo_n "checking for library containing deflate... " >&6; }
-if ${ac_cv_search_deflate+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char deflate ();
-int
-main ()
-{
-return deflate ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' z; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_deflate=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_deflate+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_deflate+:} false; then :
-
-else
-  ac_cv_search_deflate=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
-$as_echo "$ac_cv_search_deflate" >&6; }
-ac_res=$ac_cv_search_deflate
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
-
-fi
-
-              ZLIB_LIBS=" -lz"
-fi
-
-
-
-#  ----------------------------------------------------------------------
-#  Compile application with SZLIB library, needed for GRIB1 or for
-#  linking against hdf5/netcdf4
+#  Compile application with SZLIB library, needed for GRIB1
 SZLIB_INCLUDE=''
 SZLIB_LIBS=''
 
@@ -27290,325 +27037,6 @@ fi
 
 
 #  ----------------------------------------------------------------------
-#  Link application with HDF5 library, required for netcdf4
-HDF5_ROOT=''
-HDF5_INCLUDE=''
-HDF5_LIBS=''
-
-# Check whether --with-hdf5 was given.
-if test "${with_hdf5+set}" = set; then :
-  withval=$with_hdf5; case "$with_hdf5" in #(
-  no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hdf5 library" >&5
-$as_echo_n "checking for hdf5 library... " >&6; }
-                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; } ;; #(
-  yes) :
-    for ac_header in hdf5.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "hdf5.h" "ac_cv_header_hdf5_h" "$ac_includes_default"
-if test "x$ac_cv_header_hdf5_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_HDF5_H 1
-_ACEOF
-
-fi
-
-done
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5Fopen" >&5
-$as_echo_n "checking for library containing H5Fopen... " >&6; }
-if ${ac_cv_search_H5Fopen+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char H5Fopen ();
-int
-main ()
-{
-return H5Fopen ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' hdf5; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_H5Fopen=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_H5Fopen+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_H5Fopen+:} false; then :
-
-else
-  ac_cv_search_H5Fopen=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_H5Fopen" >&5
-$as_echo "$ac_cv_search_H5Fopen" >&6; }
-ac_res=$ac_cv_search_H5Fopen
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBHDF5 1" >>confdefs.h
-
-else
-  as_fn_error $? "Cannot link to hdf5 library! It is required for Netcdf4" "$LINENO" 5
-fi
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5DSis_scale" >&5
-$as_echo_n "checking for library containing H5DSis_scale... " >&6; }
-if ${ac_cv_search_H5DSis_scale+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char H5DSis_scale ();
-int
-main ()
-{
-return H5DSis_scale ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' hdf5_hl; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_H5DSis_scale=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_H5DSis_scale+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_H5DSis_scale+:} false; then :
-
-else
-  ac_cv_search_H5DSis_scale=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_H5DSis_scale" >&5
-$as_echo "$ac_cv_search_H5DSis_scale" >&6; }
-ac_res=$ac_cv_search_H5DSis_scale
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-  have_hdf5_hl=yes
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot find hdf5 high level interface! It is required for netCDF4." >&5
-$as_echo "$as_me: Cannot find hdf5 high level interface! It is required for netCDF4." >&6;}
-                                            have_hdf5_hl=no
-fi
-
-                            if test "x$have_libhdf5_hl" = xyes; then :
-  HDF5_LIBS=" -lhdf5_hl -lhdf5"
-else
-  HDF5_LIBS=" -lhdf5"
-fi
-                             ;; #(
-  *) :
-    if test -d "$with_hdf5"; then :
-  HDF5_ROOT="$with_hdf5"
-                                 LDFLAGS="-L$HDF5_ROOT/lib $LDFLAGS"
-                                 CPPFLAGS="-I$HDF5_ROOT/include $CPPFLAGS"
-                                 for ac_header in hdf5.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "hdf5.h" "ac_cv_header_hdf5_h" "$ac_includes_default"
-if test "x$ac_cv_header_hdf5_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_HDF5_H 1
-_ACEOF
-
-fi
-
-done
-
-                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5Fopen" >&5
-$as_echo_n "checking for library containing H5Fopen... " >&6; }
-if ${ac_cv_search_H5Fopen+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char H5Fopen ();
-int
-main ()
-{
-return H5Fopen ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' hdf5; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_H5Fopen=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_H5Fopen+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_H5Fopen+:} false; then :
-
-else
-  ac_cv_search_H5Fopen=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_H5Fopen" >&5
-$as_echo "$ac_cv_search_H5Fopen" >&6; }
-ac_res=$ac_cv_search_H5Fopen
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBHDF5 1" >>confdefs.h
-
-else
-  as_fn_error $? "Cannot link to hdf5! It is required for netCDF4." "$LINENO" 5
-fi
-
-                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5DSis_scale" >&5
-$as_echo_n "checking for library containing H5DSis_scale... " >&6; }
-if ${ac_cv_search_H5DSis_scale+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char H5DSis_scale ();
-int
-main ()
-{
-return H5DSis_scale ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' hdf5_hl; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_H5DSis_scale=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_H5DSis_scale+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_H5DSis_scale+:} false; then :
-
-else
-  ac_cv_search_H5DSis_scale=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_H5DSis_scale" >&5
-$as_echo "$ac_cv_search_H5DSis_scale" >&6; }
-ac_res=$ac_cv_search_H5DSis_scale
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-  have_hdf5_hl=yes
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot link to hdf5 high level interface! It is required for netCDF4.\
-                                                                HDF5 must be built with zlib; the location of zlib must be specified for HDF5 with the \
-                                                                --with-zlib option. If HDF5 was also built with szlib, then the location of szlib must also be \
-                                                                specified with the --with-szlib option.." >&5
-$as_echo "$as_me: Cannot link to hdf5 high level interface! It is required for netCDF4.\
-                                                                HDF5 must be built with zlib; the location of zlib must be specified for HDF5 with the \
-                                                                --with-zlib option. If HDF5 was also built with szlib, then the location of szlib must also be \
-                                                                specified with the --with-szlib option.." >&6;}
-                                                have_hdf5_hl=no
-fi
-
-                                 if test "x$have_libhdf5_hl" = 'xyes'; then :
-  HDF5_LIBS=" -L$HDF5_ROOT/lib -lhdf5_hl -lhdf5"
-else
-  HDF5_LIBS=" -L$HDF5_ROOT/lib -lhdf5"
-fi
-                                 HDF5_INCLUDE=" -I$HDF5_ROOT/include"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: $with_hdf5 is not a directory! HDF5 suppressed" >&5
-$as_echo "$as_me: $with_hdf5 is not a directory! HDF5 suppressed" >&6;}
-fi ;; #(
-  *) :
-     ;;
-esac
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hdf5 library" >&5
-$as_echo_n "checking for hdf5 library... " >&6; }
-             { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; }
-fi
-
-
-
-
-#  ----------------------------------------------------------------------
 #  Compile application with netcdf
 NETCDF_ROOT=''
 NETCDF_INCLUDE=''
@@ -27616,13 +27044,14 @@ NETCDF_LIBS=''
 ENABLE_NETCDF=no
 ENABLE_NC2=no
 ENABLE_NC4=no
+ENABLE_NC4HDF5=no
 
 # Check whether --with-netcdf was given.
 if test "${with_netcdf+set}" = set; then :
   withval=$with_netcdf; case "$with_netcdf" in #(
   no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for netcdf library" >&5
-$as_echo_n "checking for netcdf library... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NetCDF library" >&5
+$as_echo_n "checking for NetCDF library... " >&6; }
                            { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
 $as_echo "suppressed" >&6; } ;; #(
   yes) :
@@ -27696,7 +27125,7 @@ $as_echo "#define HAVE_LIBNETCDF 1" >>confdefs.h
 
                                             ENABLE_NETCDF=yes
 else
-  as_fn_error $? "Could not link to netcdf library" "$LINENO" 5
+  as_fn_error $? "Could not link to NetCDF library" "$LINENO" 5
 fi
 
                             NETCDF_LIBS=" -lnetcdf"
@@ -27764,6 +27193,19 @@ else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
+			           { $as_echo "$as_me:${as_lineno-$LINENO}: checking netcdf's nc4/hdf5 support" >&5
+$as_echo_n "checking netcdf's nc4/hdf5 support... " >&6; }
+                                   if test "x$($NC_CONFIG --has-hdf5)" = "xyes"; then :
+
+$as_echo "#define HAVE_NC4HDF5 1" >>confdefs.h
+
+                                          ENABLE_NC4HDF5=yes
+                                          { $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
 else
   $as_echo Could not find nc-config! go on with default configuration
 fi ;; #(
@@ -27842,7 +27284,7 @@ $as_echo "#define HAVE_LIBNETCDF 1" >>confdefs.h
 
                                                  ENABLE_NETCDF=yes
 else
-  as_fn_error $? "Could not link to netcdf library" "$LINENO" 5
+  as_fn_error $? "Could not link to NetCDF library" "$LINENO" 5
 fi
 
                                  NETCDF_LIBS=" -L$NETCDF_ROOT/lib -lnetcdf"
@@ -27889,11 +27331,11 @@ fi
                                  if test "x$NC_CONFIG" != "x"; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking netcdf's OpenDAP support" >&5
 $as_echo_n "checking netcdf's OpenDAP support... " >&6; }
-                                    if test "x$($NC_CONFIG --has-dap)" = "xyes"; then :
+                                   if test "x$($NC_CONFIG --has-dap)" = "xyes"; then :
 
 $as_echo "#define HAVE_LIBNC_DAP 1" >>confdefs.h
 
-                                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+                                          { $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
@@ -27925,25 +27367,162 @@ else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
+			           { $as_echo "$as_me:${as_lineno-$LINENO}: checking netcdf's nc4/hdf5 support" >&5
+$as_echo_n "checking netcdf's nc4/hdf5 support... " >&6; }
+                                   if test "x$($NC_CONFIG --has-hdf5)" = "xyes"; then :
+
+$as_echo "#define HAVE_NC4HDF5 1" >>confdefs.h
+
+                                          ENABLE_NC4HDF5=yes
+                                          { $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
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: Could not find nc-config! go on with default configuration" >&5
 $as_echo "Could not find nc-config! go on with default configuration" >&6; }
 fi
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: $with_netcdf is not a directory! NETCDF suppressed" >&5
-$as_echo "$as_me: $with_netcdf is not a directory! NETCDF suppressed" >&6;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: $with_netcdf is not a directory! NetCDF suppressed" >&5
+$as_echo "$as_me: $with_netcdf is not a directory! NetCDF suppressed" >&6;}
 fi ;; #(
   *) :
      ;;
 esac
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NETCDF library" >&5
-$as_echo_n "checking for NETCDF library... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NetCDF library" >&5
+$as_echo_n "checking for NetCDF library... " >&6; }
              { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
 $as_echo "suppressed" >&6; }
 fi
 
 
+if test "x$ENABLE_NC4HDF5" = "xyes"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5TS_mutex_lock" >&5
+$as_echo_n "checking for library containing H5TS_mutex_lock... " >&6; }
+if ${ac_cv_search_H5TS_mutex_lock+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char H5TS_mutex_lock ();
+int
+main ()
+{
+return H5TS_mutex_lock ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' netcdf; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_H5TS_mutex_lock=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_H5TS_mutex_lock+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_H5TS_mutex_lock+:} false; then :
+
+else
+  ac_cv_search_H5TS_mutex_lock=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_H5TS_mutex_lock" >&5
+$as_echo "$ac_cv_search_H5TS_mutex_lock" >&6; }
+ac_res=$ac_cv_search_H5TS_mutex_lock
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_NC4HDF5_THREADSAFE 1" >>confdefs.h
+
+fi
+
+fi
+
+if test "x$ENABLE_NC4HDF5" = "xyes"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing H5get_libversion" >&5
+$as_echo_n "checking for library containing H5get_libversion... " >&6; }
+if ${ac_cv_search_H5get_libversion+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char H5get_libversion ();
+int
+main ()
+{
+return H5get_libversion ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' netcdf; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_H5get_libversion=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_H5get_libversion+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_H5get_libversion+:} false; then :
+
+else
+  ac_cv_search_H5get_libversion=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_H5get_libversion" >&5
+$as_echo "$ac_cv_search_H5get_libversion" >&6; }
+ac_res=$ac_cv_search_H5get_libversion
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_H5GET_LIBVERSION 1" >>confdefs.h
+
+fi
+
+fi
+
+
+
 
 
 
@@ -31461,7 +31040,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by cdi $as_me 1.7.1, which was
+This file was extended by cdi $as_me 1.7.2, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -31527,7 +31106,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-cdi config.status 1.7.1
+cdi config.status 1.7.2
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
diff --git a/libcdi/configure.ac b/libcdi/configure.ac
index c6ed99b..578f31c 100644
--- a/libcdi/configure.ac
+++ b/libcdi/configure.ac
@@ -4,7 +4,7 @@
 #  autoconf 2.68
 #  libtool  2.4.2
 
-AC_INIT([cdi], [1.7.1], [http://mpimet.mpg.de/cdi])
+AC_INIT([cdi], [1.7.2], [http://mpimet.mpg.de/cdi])
 
 AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version])
 
diff --git a/libcdi/doc/cdi_cman.pdf b/libcdi/doc/cdi_cman.pdf
index 5334413..703625c 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 2941678..f9593d1 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 bb96dc7..c518697 100644
--- a/libcdi/examples/Makefile.am
+++ b/libcdi/examples/Makefile.am
@@ -41,4 +41,8 @@ cdi_copy_LDFLAGS         = -all-static
 cdi_read_f2003_LDFLAGS   = -all-static
 cdi_write_f2003_LDFLAGS  = -all-static
 endif
-
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
diff --git a/libcdi/examples/Makefile.in b/libcdi/examples/Makefile.in
index ad376e2..49afd26 100644
--- a/libcdi/examples/Makefile.in
+++ b/libcdi/examples/Makefile.in
@@ -285,6 +285,7 @@ ENABLE_IEG = @ENABLE_IEG@
 ENABLE_MPI = @ENABLE_MPI@
 ENABLE_NC2 = @ENABLE_NC2@
 ENABLE_NC4 = @ENABLE_NC4@
+ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
 ENABLE_NETCDF = @ENABLE_NETCDF@
 ENABLE_PYTHON = @ENABLE_PYTHON@
 ENABLE_RUBY = @ENABLE_RUBY@
@@ -307,9 +308,6 @@ GREP = @GREP@
 GRIB_API_INCLUDE = @GRIB_API_INCLUDE@
 GRIB_API_LIBS = @GRIB_API_LIBS@
 HAVE_PARALLEL_NC4 = @HAVE_PARALLEL_NC4@
-HDF5_INCLUDE = @HDF5_INCLUDE@
-HDF5_LIBS = @HDF5_LIBS@
-HDF5_ROOT = @HDF5_ROOT@
 HOST_NAME = @HOST_NAME@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -382,8 +380,6 @@ UUID_C_LIB = @UUID_C_LIB@
 VERSION = @VERSION@
 YAXT_CFLAGS = @YAXT_CFLAGS@
 YAXT_LIBS = @YAXT_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -713,7 +709,7 @@ maintainer-clean-generic:
 	@echo "it deletes files that may require special tools to rebuild."
 clean: clean-am
 
-clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
 	mostlyclean-am
 
 distclean: distclean-am
@@ -785,8 +781,8 @@ uninstall-am:
 .MAKE: install-am install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-	clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
-	ctags-am distclean distclean-compile distclean-generic \
+	clean-libtool clean-local clean-noinstPROGRAMS cscopelist-am \
+	ctags ctags-am distclean distclean-compile distclean-generic \
 	distclean-libtool distclean-tags distdir dvi dvi-am html \
 	html-am info info-am install install-am install-data \
 	install-data-am install-dvi install-dvi-am install-exec \
@@ -800,6 +796,11 @@ uninstall-am:
 
 cdi_read_f2003.$(OBJEXT): $(top_builddir)/src/mo_cdi.$(FCMODEXT)
 cdi_write_f2003.$(OBJEXT): $(top_builddir)/src/mo_cdi.$(FCMODEXT)
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
 
 # 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/pio/Makefile.am b/libcdi/examples/pio/Makefile.am
index 88bbc1a..8633ba3 100644
--- a/libcdi/examples/pio/Makefile.am
+++ b/libcdi/examples/pio/Makefile.am
@@ -28,3 +28,8 @@ collectData2003_SOURCES=collectData2003.F90
 collectDataNStreams_SOURCES = collectDataNStreams.c
 
 compareResourcesArray_SOURCES = compareResourcesArray.c
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
diff --git a/libcdi/examples/pio/Makefile.in b/libcdi/examples/pio/Makefile.in
index 5354f78..1536458 100644
--- a/libcdi/examples/pio/Makefile.in
+++ b/libcdi/examples/pio/Makefile.in
@@ -279,6 +279,7 @@ ENABLE_IEG = @ENABLE_IEG@
 ENABLE_MPI = @ENABLE_MPI@
 ENABLE_NC2 = @ENABLE_NC2@
 ENABLE_NC4 = @ENABLE_NC4@
+ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
 ENABLE_NETCDF = @ENABLE_NETCDF@
 ENABLE_PYTHON = @ENABLE_PYTHON@
 ENABLE_RUBY = @ENABLE_RUBY@
@@ -301,9 +302,6 @@ GREP = @GREP@
 GRIB_API_INCLUDE = @GRIB_API_INCLUDE@
 GRIB_API_LIBS = @GRIB_API_LIBS@
 HAVE_PARALLEL_NC4 = @HAVE_PARALLEL_NC4@
-HDF5_INCLUDE = @HDF5_INCLUDE@
-HDF5_LIBS = @HDF5_LIBS@
-HDF5_ROOT = @HDF5_ROOT@
 HOST_NAME = @HOST_NAME@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -376,8 +374,6 @@ UUID_C_LIB = @UUID_C_LIB@
 VERSION = @VERSION@
 YAXT_CFLAGS = @YAXT_CFLAGS@
 YAXT_LIBS = @YAXT_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -671,7 +667,7 @@ maintainer-clean-generic:
 	@echo "it deletes files that may require special tools to rebuild."
 clean: clean-am
 
-clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
 	mostlyclean-am
 
 distclean: distclean-am
@@ -743,8 +739,8 @@ uninstall-am:
 .MAKE: install-am install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-	clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
-	ctags-am distclean distclean-compile distclean-generic \
+	clean-libtool clean-local clean-noinstPROGRAMS cscopelist-am \
+	ctags ctags-am distclean distclean-compile distclean-generic \
 	distclean-libtool distclean-tags distdir dvi dvi-am html \
 	html-am info info-am install install-am install-data \
 	install-data-am install-dvi install-dvi-am install-exec \
@@ -756,6 +752,11 @@ uninstall-am:
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
 	tags tags-am uninstall uninstall-am
 
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
 
 # 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/interfaces/Makefile.am b/libcdi/interfaces/Makefile.am
index 473f945..0b908cf 100644
--- a/libcdi/interfaces/Makefile.am
+++ b/libcdi/interfaces/Makefile.am
@@ -30,15 +30,15 @@ noinst_PROGRAMS += CdiInfo
 noinst_LTLIBRARIES += libcdipp.la
 endif
 #
-locallibs = $(top_builddir)/src/.libs/libcdi.so @LTLIBOBJS@ @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@
+locallibs = $(top_builddir)/src/.libs/libcdi.so @LTLIBOBJS@ @NETCDF_LIBS@ @SZLIB_LIBS@
 
 libcdipp_la_SOURCES = cdi.cpp cdi.hpp
 libcdipp_la_LIBADD  = $(top_builddir)/src/libcdi.la
-libcdipp_la_LDFLAGS = @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@ $(LDFLAGS)
+libcdipp_la_LDFLAGS = @NETCDF_LIBS@ @SZLIB_LIBS@ $(LDFLAGS)
 
 CdiInfo_SOURCES     = CdiInfo.cpp
 CdiInfo_LDADD       = libcdipp.la
-CdiInfo_LDFLAGS     = @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@ $(LDFLAGS)
+CdiInfo_LDFLAGS     = @NETCDF_LIBS@ @SZLIB_LIBS@ $(LDFLAGS)
 #
 #
 if ENABLE_RUBY
diff --git a/libcdi/interfaces/Makefile.in b/libcdi/interfaces/Makefile.in
index 0bf972d..a7c5b60 100644
--- a/libcdi/interfaces/Makefile.in
+++ b/libcdi/interfaces/Makefile.in
@@ -263,6 +263,7 @@ ENABLE_IEG = @ENABLE_IEG@
 ENABLE_MPI = @ENABLE_MPI@
 ENABLE_NC2 = @ENABLE_NC2@
 ENABLE_NC4 = @ENABLE_NC4@
+ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
 ENABLE_NETCDF = @ENABLE_NETCDF@
 ENABLE_PYTHON = @ENABLE_PYTHON@
 ENABLE_RUBY = @ENABLE_RUBY@
@@ -285,9 +286,6 @@ GREP = @GREP@
 GRIB_API_INCLUDE = @GRIB_API_INCLUDE@
 GRIB_API_LIBS = @GRIB_API_LIBS@
 HAVE_PARALLEL_NC4 = @HAVE_PARALLEL_NC4@
-HDF5_INCLUDE = @HDF5_INCLUDE@
-HDF5_LIBS = @HDF5_LIBS@
-HDF5_ROOT = @HDF5_ROOT@
 HOST_NAME = @HOST_NAME@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -360,8 +358,6 @@ UUID_C_LIB = @UUID_C_LIB@
 VERSION = @VERSION@
 YAXT_CFLAGS = @YAXT_CFLAGS@
 YAXT_LIBS = @YAXT_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -440,13 +436,13 @@ EXTRA_DIST = $(SWIGCDIOBJ) $(SWIGCDILIB) \
 
 noinst_LTLIBRARIES = $(am__append_3)
 #
-locallibs = $(top_builddir)/src/.libs/libcdi.so @LTLIBOBJS@ @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@
+locallibs = $(top_builddir)/src/.libs/libcdi.so @LTLIBOBJS@ @NETCDF_LIBS@ @SZLIB_LIBS@
 libcdipp_la_SOURCES = cdi.cpp cdi.hpp
 libcdipp_la_LIBADD = $(top_builddir)/src/libcdi.la
-libcdipp_la_LDFLAGS = @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@ $(LDFLAGS)
+libcdipp_la_LDFLAGS = @NETCDF_LIBS@ @SZLIB_LIBS@ $(LDFLAGS)
 CdiInfo_SOURCES = CdiInfo.cpp
 CdiInfo_LDADD = libcdipp.la
-CdiInfo_LDFLAGS = @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@ $(LDFLAGS)
+CdiInfo_LDFLAGS = @NETCDF_LIBS@ @SZLIB_LIBS@ $(LDFLAGS)
 #
 AM_CPPFLAGS = -I$(top_srcdir)/src
 #
diff --git a/libcdi/m4/acx_options.m4 b/libcdi/m4/acx_options.m4
index fa5cbf8..8782e58 100644
--- a/libcdi/m4/acx_options.m4
+++ b/libcdi/m4/acx_options.m4
@@ -27,32 +27,7 @@ AS_CASE([$with_threads],
 AC_SUBST([THREADS_INCLUDE])
 AC_SUBST([THREADS_LIBS])
 #  ----------------------------------------------------------------------
-#  Link application to ZLIB library, needed for netcdf
-ZLIB_INCLUDE=''
-ZLIB_LIBS=''
-AC_ARG_WITH([zlib],
-            [AS_HELP_STRING([--with-zlib=<yes|no|directory> (default=yes)],[location of ZLIB compression library (lib and include subdirs), nec. for HDF5/NETCDF4])],
-            [AS_CASE(["$with_zlib"],
-                     [no],[AC_MSG_CHECKING([for ZLIB library])
-                           AC_MSG_RESULT([suppressed])],
-                     [yes],[AC_CHECK_HEADERS(zlib.h)
-                            AC_SEARCH_LIBS([deflate],[z],[AC_DEFINE([HAVE_LIBZ],[1],[Define 1 for ZLIB support])])
-                            ZLIB_LIBS=" -lz"],
-                     [*],[ZLIB_ROOT=$with_zlib
-                          LDFLAGS="-L$ZLIB_ROOT/lib $LDFLAGS"
-                          CPPFLAGS="-I$ZLIB_ROOT/include $CPPFLAGS"
-                          AC_CHECK_HEADERS(zlib.h)
-                          AC_SEARCH_LIBS([deflate],[z],[AC_DEFINE([HAVE_LIBZ],[1],[Define 1 for ZLIB support])])
-                          ZLIB_INCLUDE=" -I$ZLIB_ROOT/include"
-                          ZLIB_LIBS=" -L$ZLIB_ROOT/lib -lz"])],
-                     [AC_CHECK_HEADERS(zlib.h)
-                      AC_SEARCH_LIBS([deflate],[z],[AC_DEFINE([HAVE_LIBZ],[1],[Define 1 for ZLIB support])])
-              ZLIB_LIBS=" -lz"])
-AC_SUBST([ZLIB_INCLUDE])
-AC_SUBST([ZLIB_LIBS])
-#  ----------------------------------------------------------------------
-#  Compile application with SZLIB library, needed for GRIB1 or for
-#  linking against hdf5/netcdf4
+#  Compile application with SZLIB library, needed for GRIB1
 SZLIB_INCLUDE=''
 SZLIB_LIBS=''
 AC_ARG_WITH([szlib],
@@ -83,57 +58,6 @@ AC_ARG_WITH([szlib],
 AC_SUBST([SZLIB_INCLUDE])
 AC_SUBST([SZLIB_LIBS])
 #  ----------------------------------------------------------------------
-#  Link application with HDF5 library, required for netcdf4
-HDF5_ROOT=''
-HDF5_INCLUDE=''
-HDF5_LIBS=''
-AC_ARG_WITH([hdf5],
-            [AS_HELP_STRING([--with-hdf5=<yes|no|directory> (default=no)],[location of hdf5 library, NETCDF4 requires hdf5 high level interface])],
-            [AS_CASE(["$with_hdf5"],
-                     [no],[AC_MSG_CHECKING([for hdf5 library])
-                           AC_MSG_RESULT([suppressed])],
-                     [yes],[AC_CHECK_HEADERS([hdf5.h])
-                            AC_SEARCH_LIBS([H5Fopen],
-                                           [hdf5],
-                                           [AC_DEFINE([HAVE_LIBHDF5],[1],[Define to 1 for HDF5 support])],
-                                           [AC_MSG_ERROR([Cannot link to hdf5 library! It is required for Netcdf4])])
-                            AC_SEARCH_LIBS([H5DSis_scale],
-                                           [hdf5_hl],
-                                           [have_hdf5_hl=yes],
-                                           [AC_MSG_NOTICE([Cannot find hdf5 high level interface! It is required for netCDF4.])
-                                            have_hdf5_hl=no])
-                            AS_IF([test "x$have_libhdf5_hl" = xyes],
-                                  [HDF5_LIBS=" -lhdf5_hl -lhdf5"],
-                                  [HDF5_LIBS=" -lhdf5"])
-                            ],
-                     [*],[AS_IF([test -d "$with_hdf5"],
-                                [HDF5_ROOT="$with_hdf5"
-                                 LDFLAGS="-L$HDF5_ROOT/lib $LDFLAGS"
-                                 CPPFLAGS="-I$HDF5_ROOT/include $CPPFLAGS"
-                                 AC_CHECK_HEADERS([hdf5.h])
-                                 AC_SEARCH_LIBS([H5Fopen],
-                                                [hdf5],
-                                                [AC_DEFINE([HAVE_LIBHDF5],[1],[Define to 1 for HDF5 support])],
-                                                [AC_MSG_ERROR([Cannot link to hdf5! It is required for netCDF4.])])
-                                 AC_SEARCH_LIBS([H5DSis_scale],
-                                                [hdf5_hl],
-                                                [have_hdf5_hl=yes],
-                                                [AC_MSG_NOTICE([Cannot link to hdf5 high level interface! It is required for netCDF4.\
-                                                                HDF5 must be built with zlib; the location of zlib must be specified for HDF5 with the \
-                                                                --with-zlib option. If HDF5 was also built with szlib, then the location of szlib must also be \
-                                                                specified with the --with-szlib option..])
-                                                have_hdf5_hl=no])
-                                 AS_IF([test "x$have_libhdf5_hl" = 'xyes'],
-                                       [HDF5_LIBS=" -L$HDF5_ROOT/lib -lhdf5_hl -lhdf5"],
-                                       [HDF5_LIBS=" -L$HDF5_ROOT/lib -lhdf5"])
-                                 HDF5_INCLUDE=" -I$HDF5_ROOT/include"],
-                                [AC_MSG_NOTICE([$with_hdf5 is not a directory! HDF5 suppressed])])])],
-            [AC_MSG_CHECKING([for hdf5 library])
-             AC_MSG_RESULT([suppressed])])
-AC_SUBST([HDF5_ROOT])
-AC_SUBST([HDF5_INCLUDE])
-AC_SUBST([HDF5_LIBS])
-#  ----------------------------------------------------------------------
 #  Compile application with netcdf
 NETCDF_ROOT=''
 NETCDF_INCLUDE=''
@@ -141,30 +65,36 @@ NETCDF_LIBS=''
 ENABLE_NETCDF=no
 ENABLE_NC2=no
 ENABLE_NC4=no
+ENABLE_NC4HDF5=no
 AC_ARG_WITH([netcdf],
-            [AS_HELP_STRING([--with-netcdf=<yes|no|directory> (default=no)],[location of netcdf library (lib and include subdirs)])],
+            [AS_HELP_STRING([--with-netcdf=<yes|no|directory> (default=no)],[location of NetCDF library (lib and include subdirs)])],
             [AS_CASE(["$with_netcdf"],
-                     [no],[AC_MSG_CHECKING([for netcdf library])
+                     [no],[AC_MSG_CHECKING([for NetCDF library])
                            AC_MSG_RESULT([suppressed])],
                      [yes],[AC_CHECK_HEADERS([netcdf.h])
                             AC_SEARCH_LIBS([nc_open],
                                            [netcdf],
-                                           [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for NETCDF support])
+                                           [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for NetCDF support])
                                             ENABLE_NETCDF=yes],
-                                           [AC_MSG_ERROR([Could not link to netcdf library])])
+                                           [AC_MSG_ERROR([Could not link to NetCDF library])])
                             NETCDF_LIBS=" -lnetcdf"
                             AC_CHECK_PROG(NC_CONFIG,nc-config,nc-config)
                             AS_IF([test "x$NC_CONFIG" != "x"],
                                   [AC_MSG_CHECKING([netcdf's nc2 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc2)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for NETCDF2 support])
+                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for NetCDF2 support])
                                           ENABLE_NC2=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
                                    AC_MSG_CHECKING([netcdf's nc4 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc4)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NETCDF4 support])
+                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NetCDF4 support])
                                           ENABLE_NC4=yes
-                                          AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])],
+                                          AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
+			           AC_MSG_CHECKING([netcdf's nc4/hdf5 support])
+                                   AS_IF([test "x$($NC_CONFIG --has-hdf5)" = "xyes"],
+                                         [AC_DEFINE([HAVE_NC4HDF5],[1],[Define to 1 for NetCDF4/HDF5 support])
+                                          ENABLE_NC4HDF5=yes
+                                          AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])]) ],
                                   [AS_ECHO([Could not find nc-config! go on with default configuration])])],
                      [*],[AS_IF([test -d "$with_netcdf"],
                                 [NETCDF_ROOT=$with_netcdf
@@ -173,35 +103,50 @@ AC_ARG_WITH([netcdf],
                                  AC_CHECK_HEADERS([netcdf.h])
                                  AC_SEARCH_LIBS([nc_open],
                                                 [netcdf],
-                                                [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for NETCDF support])
+                                                [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for NetCDF support])
                                                  ENABLE_NETCDF=yes],
-                                                [AC_MSG_ERROR([Could not link to netcdf library])])
+                                                [AC_MSG_ERROR([Could not link to NetCDF library])])
                                  NETCDF_LIBS=" -L$NETCDF_ROOT/lib -lnetcdf"
                                  NETCDF_INCLUDE=" -I$NETCDF_ROOT/include"
                                  AC_MSG_CHECKING([nc-config script])
                                  AC_CHECK_PROG(NC_CONFIG,nc-config,[$NETCDF_ROOT/bin/nc-config],,["$NETCDF_ROOT/bin"])
                                  AS_IF([test "x$NC_CONFIG" != "x"],
                                    [AC_MSG_CHECKING([netcdf's OpenDAP support])
-                                    AS_IF([test "x$($NC_CONFIG --has-dap)" = "xyes"],
-                                          [AC_DEFINE([HAVE_LIBNC_DAP],[1],[Define to 1 for NETCDF OpenDAP])
-                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])]
+                                   AS_IF([test "x$($NC_CONFIG --has-dap)" = "xyes"],
+                                         [AC_DEFINE([HAVE_LIBNC_DAP],[1],[Define to 1 for NetCDF OpenDAP])
+                                          AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])]
                                    [AC_MSG_CHECKING([netcdf's nc2 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc2)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for NETCDF2 support])
+                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for NetCDF2 support])
                                           ENABLE_NC2=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
                                    AC_MSG_CHECKING([netcdf's nc4 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc4)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NETCDF4 support])
+                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NetCDF4 support])
                                           ENABLE_NC4=yes
-                                          AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])],
+                                          AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
+			           AC_MSG_CHECKING([netcdf's nc4/hdf5 support])
+                                   AS_IF([test "x$($NC_CONFIG --has-hdf5)" = "xyes"],
+                                         [AC_DEFINE([HAVE_NC4HDF5],[1],[Define to 1 for NetCDF4/HDF5 support])
+                                          ENABLE_NC4HDF5=yes
+                                          AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])]) ],
                                    [AC_MSG_RESULT([Could not find nc-config! go on with default configuration])])],
-                                [AC_MSG_NOTICE([$with_netcdf is not a directory! NETCDF suppressed])])])],
-            [AC_MSG_CHECKING([for NETCDF library])
+                                [AC_MSG_NOTICE([$with_netcdf is not a directory! NetCDF suppressed])])])],
+            [AC_MSG_CHECKING([for NetCDF library])
              AC_MSG_RESULT([suppressed])])
+
+AS_IF([test "x$ENABLE_NC4HDF5" = "xyes"],
+      [AC_SEARCH_LIBS([H5TS_mutex_lock], [netcdf],
+               [AC_DEFINE([HAVE_NC4HDF5_THREADSAFE],[1],[Define to 1 for NetCDF4/HDF5 threadsafe support])],,)])
+
+AS_IF([test "x$ENABLE_NC4HDF5" = "xyes"],
+      [AC_SEARCH_LIBS([H5get_libversion], [netcdf],
+               [AC_DEFINE([HAVE_H5GET_LIBVERSION],[1],[Define to 1 for H5get_libversion support])],,)])
+
 AC_SUBST([ENABLE_NETCDF])
 AC_SUBST([ENABLE_NC2])
 AC_SUBST([ENABLE_NC4])
+AC_SUBST([ENABLE_NC4HDF5])
 AC_SUBST([NETCDF_ROOT])
 AC_SUBST([NETCDF_INCLUDE])
 AC_SUBST([NETCDF_LIBS])
diff --git a/libcdi/src/Makefile.am b/libcdi/src/Makefile.am
index eb933b6..bc78a1e 100644
--- a/libcdi/src/Makefile.am
+++ b/libcdi/src/Makefile.am
@@ -248,6 +248,8 @@ pkgconfig/cdi.pc: pkgconfig/cdi.pc.in ../config.status
 
 pkgconfig/cdipio.pc: pkgconfig/cdipio.pc.in ../config.status
 	(cd .. ; ./config.status src/pkgconfig/cdipio.pc)
+cdilib.c: 
+	(cd $(top_srcdir)/src ; ./make_cdilib )
 #
 all-local: $(LOCALTARGETS)
 #
diff --git a/libcdi/src/Makefile.in b/libcdi/src/Makefile.in
index ab7d81c..ec0a5df 100644
--- a/libcdi/src/Makefile.in
+++ b/libcdi/src/Makefile.in
@@ -348,6 +348,7 @@ ENABLE_IEG = @ENABLE_IEG@
 ENABLE_MPI = @ENABLE_MPI@
 ENABLE_NC2 = @ENABLE_NC2@
 ENABLE_NC4 = @ENABLE_NC4@
+ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
 ENABLE_NETCDF = @ENABLE_NETCDF@
 ENABLE_PYTHON = @ENABLE_PYTHON@
 ENABLE_RUBY = @ENABLE_RUBY@
@@ -370,9 +371,6 @@ GREP = @GREP@
 GRIB_API_INCLUDE = @GRIB_API_INCLUDE@
 GRIB_API_LIBS = @GRIB_API_LIBS@
 HAVE_PARALLEL_NC4 = @HAVE_PARALLEL_NC4@
-HDF5_INCLUDE = @HDF5_INCLUDE@
-HDF5_LIBS = @HDF5_LIBS@
-HDF5_ROOT = @HDF5_ROOT@
 HOST_NAME = @HOST_NAME@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -445,8 +443,6 @@ UUID_C_LIB = @UUID_C_LIB@
 VERSION = @VERSION@
 YAXT_CFLAGS = @YAXT_CFLAGS@
 YAXT_LIBS = @YAXT_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -946,8 +942,8 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
- at ENABLE_CDI_LIB_FALSE@uninstall-local:
 @ENABLE_CDI_LIB_FALSE at install-exec-local:
+ at ENABLE_CDI_LIB_FALSE@uninstall-local:
 clean: clean-am
 
 clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
@@ -1054,6 +1050,8 @@ pkgconfig/cdi.pc: pkgconfig/cdi.pc.in ../config.status
 
 pkgconfig/cdipio.pc: pkgconfig/cdipio.pc.in ../config.status
 	(cd .. ; ./config.status src/pkgconfig/cdipio.pc)
+cdilib.c: 
+	(cd $(top_srcdir)/src ; ./make_cdilib )
 #
 all-local: $(LOCALTARGETS)
 
diff --git a/libcdi/src/binary.h b/libcdi/src/binary.h
index 1bd560f..26a0a6d 100644
--- a/libcdi/src/binary.h
+++ b/libcdi/src/binary.h
@@ -8,9 +8,7 @@
 #include <inttypes.h>
 #include <stdio.h>
 
-#ifndef _DTYPES_H
 #include "dtypes.h"
-#endif
 
 #ifndef HOST_ENDIANNESS
 #ifdef __cplusplus
diff --git a/libcdi/src/calendar.c b/libcdi/src/calendar.c
index ea4be87..a40a65c 100644
--- a/libcdi/src/calendar.c
+++ b/libcdi/src/calendar.c
@@ -14,35 +14,33 @@ static int month_366[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
 int calendar_dpy(int calendar)
 {
-  int dpy = 0;
+  int daysperyear = 0;
 
-  if      ( calendar == CALENDAR_360DAYS ) dpy = 360;
-  else if ( calendar == CALENDAR_365DAYS ) dpy = 365;
-  else if ( calendar == CALENDAR_366DAYS ) dpy = 366;
+  if      ( calendar == CALENDAR_360DAYS ) daysperyear = 360;
+  else if ( calendar == CALENDAR_365DAYS ) daysperyear = 365;
+  else if ( calendar == CALENDAR_366DAYS ) daysperyear = 366;
 
-  return (dpy);
+  return daysperyear;
 }
 
 
 int days_per_month(int calendar, int year, int month)
 {
-  int dayspermonth = 0;
   int *dpm = NULL;
-  int dpy;
+  int daysperyear = calendar_dpy(calendar);
 
-  dpy = calendar_dpy(calendar);
-
-  if      ( dpy == 360 ) dpm = month_360;
-  else if ( dpy == 365 ) dpm = month_365;
-  else                   dpm = month_366;
+  if      ( daysperyear == 360 ) dpm = month_360;
+  else if ( daysperyear == 365 ) dpm = month_365;
+  else                           dpm = month_366;
 
+  int dayspermonth = 0;
   if ( month >= 1 && month <= 12 )
     dayspermonth = dpm[month-1];
   /*
   else
     fprintf(stderr, "days_per_month: month %d out of range\n", month);
   */
-  if ( dpy == 0 && month == 2 )
+  if ( daysperyear == 0 && month == 2 )
     {
       if ( (year%4 == 0 && year%100 != 0) || year%400 == 0 )
 	dayspermonth = 29;
@@ -50,40 +48,25 @@ int days_per_month(int calendar, int year, int month)
 	dayspermonth = 28;
     }
 
-  return (dayspermonth);
+  return dayspermonth;
 }
 
 
 int days_per_year(int calendar, int year)
 {
-  int daysperyear;
-  int dpy;
+  int daysperyear = calendar_dpy(calendar);
 
-  dpy = calendar_dpy(calendar);
-
-  if ( dpy == 0 )
+  if ( daysperyear == 0 )
     {
-      if ( calendar == CALENDAR_STANDARD )
-	{
-	  if ( year == 1582 )
-	    dpy = 355;
-	  else if ( (year%4 == 0 && year%100 != 0) || year%400 == 0 )
-	    dpy = 366;
-	  else
-	    dpy = 365;
-	}
+      if ( year == 1582 && calendar == CALENDAR_STANDARD )
+        daysperyear = 355;
+      else if ( (year%4 == 0 && year%100 != 0) || year%400 == 0 )
+        daysperyear = 366;
       else
-	{
-	  if ( (year%4 == 0 && year%100 != 0) || year%400 == 0 )
-	    dpy = 366;
-	  else
-	    dpy = 365;
-	}
+        daysperyear = 365;
     }
 
-  daysperyear = dpy;
-  
-  return (daysperyear);
+  return daysperyear;
 }
 
 
@@ -113,7 +96,6 @@ static void decode_day(int dpy, int days, int *year, int *month, int *day)
 
 static int encode_day(int dpy, int year, int month, int day)
 {
-  int i;
   int *dpm = NULL;
   long rval = (long)dpy * year + day;
 
@@ -121,8 +103,8 @@ static int encode_day(int dpy, int year, int month, int day)
   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)
+  if ( dpm ) for ( int i = 0; i < month-1; i++ ) rval += dpm[i];
+  if ( rval > INT_MAX || rval < INT_MIN )
     Error("Unhandled date: %ld", rval);
 
   return (int)rval;
@@ -132,9 +114,7 @@ static int encode_day(int dpy, int year, int month, int day)
 void encode_caldaysec(int calendar, int year, int month, int day, int hour, int minute, int second,
 		      int *julday, int *secofday)
 {
-  int dpy;
-
-  dpy = calendar_dpy(calendar);
+  int dpy = calendar_dpy(calendar);
 
   if ( dpy == 360 || dpy == 365 || dpy == 366 )
     *julday = encode_day(dpy, year, month, day);
@@ -145,12 +125,10 @@ void encode_caldaysec(int calendar, int year, int month, int day, int hour, int
 }
 
 
-void decode_caldaysec(int calendar, int julday, int secofday, 
+void decode_caldaysec(int calendar, int julday, int secofday,
 		      int *year, int *month, int *day, int *hour, int *minute, int *second)
 {
-  int dpy;
-
-  dpy = calendar_dpy(calendar);
+  int dpy = calendar_dpy(calendar);
 
   if ( dpy == 360 || dpy == 365 || dpy == 366 )
     decode_day(dpy, julday, year, month, day);
@@ -166,39 +144,34 @@ void decode_caldaysec(int calendar, int julday, int secofday,
 #ifdef TEST
 static int date_to_calday(int calendar, int date)
 {
-  int calday;
-  int dpy;
-  int year, month, day;
-
-  dpy = calendar_dpy(calendar);
+  int dpy = calendar_dpy(calendar);
 
+  int year, month, day;
   cdiDecodeDate(date, &year, &month, &day);
 
+  int calday;
   if ( dpy == 360 || dpy == 365 || dpy == 366 )
     calday = encode_day(dpy, year, month, day);
   else
     calday = encode_julday(calendar, year, month, day);
 
-  return (calday);
+  return calday;
 }
 
 
 static int calday_to_date(int calendar, int calday)
 {
-  int date;
-  int dpy;
   int year, month, day;
-
-  dpy = calendar_dpy(calendar);
+  int dpy = calendar_dpy(calendar);
 
   if ( dpy == 360 || dpy == 365 || dpy == 366 )
     decode_day(dpy, calday, &year, &month, &day);
   else
     decode_julday(calendar, calday, &year, &month, &day);
 
-  date = cdiEncodeDate(year, month, day);
+  int date = cdiEncodeDate(year, month, day);
 
-  return (date);
+  return date;
 }
 
 
diff --git a/libcdi/src/cdf.c b/libcdi/src/cdf.c
index 867e97e..6fb0a85 100644
--- a/libcdi/src/cdf.c
+++ b/libcdi/src/cdf.c
@@ -17,14 +17,14 @@
 const char *cdfLibraryVersion(void)
 {
 #if  defined  (HAVE_LIBNETCDF)
-  return (nc_inq_libvers());
+  return nc_inq_libvers();
 #else
-  return ("library undefined");
+  return "library undefined";
 #endif
 }
 
-#if  defined(HAVE_LIBHDF5)
-#if defined(__cplusplus)
+#if  defined(HAVE_H5GET_LIBVERSION)
+#if  defined(__cplusplus)
 extern "C" {
 #endif
   int H5get_libversion(unsigned *, unsigned *, unsigned *);
@@ -35,17 +35,20 @@ extern "C" {
 
 const char *hdfLibraryVersion(void)
 {
-#if  defined(HAVE_LIBHDF5)
+#if  defined(HAVE_H5GET_LIBVERSION)
   static char hdf_libvers[256];
   unsigned majnum, minnum, relnum;
 
   H5get_libversion(&majnum, &minnum, &relnum);
 
+#if  defined(HAVE_NC4HDF5_THREADSAFE)
+  sprintf(hdf_libvers, "%u.%u.%u threadsafe", majnum, minnum, relnum);
+#else
   sprintf(hdf_libvers, "%u.%u.%u", majnum, minnum, relnum);
-
-  return (hdf_libvers);
+#endif
+  return hdf_libvers;
 #else
-  return ("library undefined");
+  return "library undefined";
 #endif
 }
 
@@ -137,24 +140,23 @@ static int cdfOpenFile(const char *filename, const char *mode, int *filetype)
     }
 #endif
 
-  return (ncid);
+  return ncid;
 }
 
 
 int cdfOpen(const char *filename, const char *mode)
 {
-  int fileID = 0;
   int filetype = FILETYPE_NC;
 
   if ( CDF_Debug )
     Message("Open %s with mode %c", filename, *mode);
 
-  fileID = cdfOpenFile(filename, mode, &filetype);
+  int fileID = cdfOpenFile(filename, mode, &filetype);
 
   if ( CDF_Debug )
     Message("File %s opened with id %d", filename, fileID);
 
-  return (fileID);
+  return fileID;
 }
 
 
@@ -185,7 +187,7 @@ int cdfOpen64(const char *filename, const char *mode)
       fileID = CDI_ELIBNAVAIL;
     }
 
-  return (fileID);
+  return fileID;
 }
 
 
@@ -213,7 +215,7 @@ int cdf4Open(const char *filename, const char *mode, int *filetype)
       fileID = CDI_ELIBNAVAIL;
     }
 
-  return (fileID);
+  return fileID;
 }
 
 
diff --git a/libcdi/src/cdf_read.c b/libcdi/src/cdf_read.c
index 5c872f7..3445640 100644
--- a/libcdi/src/cdf_read.c
+++ b/libcdi/src/cdf_read.c
@@ -578,15 +578,13 @@ void cdf_read_var(stream_t *streamptr, int varID, int memtype, void *data, int *
 static
 void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
 {
-  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;
 
+  size_t start[4], count[4];
   bool swapxy;
   cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
 
@@ -604,19 +602,20 @@ void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data
         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);
-      if ( xtype == NC_BYTE )
-        {
-          for ( size_t i = 0; i < gridsize; i++ )
-            if ( data[i] < 0 ) data[i] += 256;
-        }
-    }
   else
     {
       cdf_get_vara_double(fileID, ncvarid, start, count, data);
+      
+      if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+        {
+          nc_type xtype;
+          cdf_inq_vartype(fileID, ncvarid, &xtype);
+          if ( xtype == NC_BYTE )
+            {
+              for ( size_t i = 0; i < gridsize; i++ )
+                if ( data[i] < 0 ) data[i] += 256;
+            }
+        }
     }
 
   if ( swapxy ) transpose2dArrayDP(ysize, xsize, data);
@@ -636,15 +635,13 @@ void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data
 static
 void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss)
 {
-  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;
 
+  size_t start[4], count[4];
   bool swapxy;
   cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
 
@@ -662,19 +659,20 @@ void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data,
         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 ( size_t i = 0; i < gridsize; i++ )
-            if ( data[i] < 0 ) data[i] += 256;
-        }
-    }
   else
     {
       cdf_get_vara_float(fileID, ncvarid, start, count, data);
+
+      if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+        {
+          nc_type xtype;
+          cdf_inq_vartype(fileID, ncvarid, &xtype);
+          if ( xtype == NC_BYTE )
+            {
+              for ( size_t i = 0; i < gridsize; i++ )
+                if ( data[i] < 0 ) data[i] += 256;
+            }
+        }
     }
 
   if ( swapxy ) transpose2dArraySP(ysize, xsize, data);
diff --git a/libcdi/src/cdi.h b/libcdi/src/cdi.h
index 7231b6a..69b253d 100644
--- a/libcdi/src/cdi.h
+++ b/libcdi/src/cdi.h
@@ -539,6 +539,8 @@ int     vlistInqVarZaxis(int vlistID, int varID);
 int     vlistInqVarID(int vlistID, int code);
 
 void    vlistDefVarTsteptype(int vlistID, int varID, int tsteptype);
+
+/*      vlistInqVarTsteptype: Get the timestep type of a Variable */
 int     vlistInqVarTsteptype(int vlistID, int varID);
 
 void    vlistDefVarCompType(int vlistID, int varID, int comptype);
@@ -754,6 +756,23 @@ void    gridDefYvals(int gridID, const double yvals[]);
 /*      gridInqYvals: Get all values of a Y-axis */
 int     gridInqYvals(int gridID, double yvals[]);
 
+/* CDI grid string key values */
+#define  CDI_GRID_XNAME      901  // X-axis name
+#define  CDI_GRID_YNAME      902  // Y-axis name
+#define  CDI_GRID_XDIMNAME   903  // X-axis dimension name
+#define  CDI_GRID_YDIMNAME   904  // Y-axis dimension name
+#define  CDI_GRID_VDIMNAME   905  // Vertex dimension name
+#define  CDI_GRID_XLONGNAME  906  // X-axis longname
+#define  CDI_GRID_YLONGNAME  907  // Y-axis longname
+#define  CDI_GRID_XUNITS     908  // X-axis units
+#define  CDI_GRID_YUNITS     909  // Y-axis units
+
+//      cdiGridDefString: Define a CDI grid string value from a key
+int     cdiGridDefString(int gridID, int key, int size, const char *mesg);
+
+//      cdiGridInqString: Get a CDI grid string value from a key
+int     cdiGridInqString(int gridID, int key, int size, char *mesg);
+
 /*      gridDefXname: Define the name of a X-axis */
 void    gridDefXname(int gridID, const char *xname);
 
@@ -960,6 +979,19 @@ void    zaxisDefUUID(int zaxisID, const unsigned char uuid[CDI_UUID_SIZE]);
 /*      zaxisInqUUID: Get the UUID of a generalized Z-axis */
 void    zaxisInqUUID(int zaxisID, unsigned char uuid[CDI_UUID_SIZE]);
 
+/* CDI zaxis string key values */
+#define  CDI_ZAXIS_NAME      801  // Z-axis name
+#define  CDI_ZAXIS_DIMNAME   802  // Z-axis dimension name
+#define  CDI_ZAXIS_VDIMNAME  803  // Vertex dimension name
+#define  CDI_ZAXIS_LONGNAME  804  // Z-axis longname
+#define  CDI_ZAXIS_UNITS     805  // Z-axis units
+
+//      cdiZaxisDefString: Define a CDI Z-axis string value from a key
+int     cdiZaxisDefString(int zaxisID, int key, int size, const char *mesg);
+
+//      cdiZaxisInqString: Get a CDI Z-axis string value from a key
+int     cdiZaxisInqString(int zaxisID, int key, int size, char *mesg);
+
 /*      zaxisDefName: Define the name of a Z-axis */
 void    zaxisDefName(int zaxisID, const char *name_optional);
 
diff --git a/libcdi/src/cdi.inc b/libcdi/src/cdi.inc
index eb83f8c..333e1e2 100644
--- a/libcdi/src/cdi.inc
+++ b/libcdi/src/cdi.inc
@@ -1,10 +1,10 @@
 ! This file was automatically generated, don't edit!
 !
-! Fortran interface for CDI library version 1.7.1
+! Fortran interface for CDI library version 1.7.2
 !
 ! Author:
 ! -------
-! Uwe Schulzweida, MPI-MET, Hamburg,   February 2016
+! Uwe Schulzweida, MPI-MET, Hamburg,   April 2016
 !
 
       INTEGER    CDI_MAX_NAME          
@@ -1523,6 +1523,41 @@
 !                                     DOUBLEPRECISION yvals(*))
       EXTERNAL        gridInqYvals
 
+!
+!  CDI grid string key values
+!
+      INTEGER    CDI_GRID_XNAME        
+      PARAMETER (CDI_GRID_XNAME         = 901)
+      INTEGER    CDI_GRID_YNAME        
+      PARAMETER (CDI_GRID_YNAME         = 902)
+      INTEGER    CDI_GRID_XDIMNAME     
+      PARAMETER (CDI_GRID_XDIMNAME      = 903)
+      INTEGER    CDI_GRID_YDIMNAME     
+      PARAMETER (CDI_GRID_YDIMNAME      = 904)
+      INTEGER    CDI_GRID_VDIMNAME     
+      PARAMETER (CDI_GRID_VDIMNAME      = 905)
+      INTEGER    CDI_GRID_XLONGNAME    
+      PARAMETER (CDI_GRID_XLONGNAME     = 906)
+      INTEGER    CDI_GRID_YLONGNAME    
+      PARAMETER (CDI_GRID_YLONGNAME     = 907)
+      INTEGER    CDI_GRID_XUNITS       
+      PARAMETER (CDI_GRID_XUNITS        = 908)
+      INTEGER    CDI_GRID_YUNITS       
+      PARAMETER (CDI_GRID_YUNITS        = 909)
+      INTEGER         cdiGridDefString
+!                                    (INTEGER         gridID,
+!                                     INTEGER         key,
+!                                     INTEGER         size,
+!                                     CHARACTER*(*)   mesg)
+      EXTERNAL        cdiGridDefString
+
+      INTEGER         cdiGridInqString
+!                                    (INTEGER         gridID,
+!                                     INTEGER         key,
+!                                     INTEGER         size,
+!                                     CHARACTER*(*)   mesg)
+      EXTERNAL        cdiGridInqString
+
 !                     gridDefXname
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   xname)
@@ -1967,6 +2002,33 @@
 !                                     INTEGER*1(16)   uuid)
       EXTERNAL        zaxisInqUUID
 
+!
+!  CDI zaxis string key values
+!
+      INTEGER    CDI_ZAXIS_NAME        
+      PARAMETER (CDI_ZAXIS_NAME         = 801)
+      INTEGER    CDI_ZAXIS_DIMNAME     
+      PARAMETER (CDI_ZAXIS_DIMNAME      = 802)
+      INTEGER    CDI_ZAXIS_VDIMNAME    
+      PARAMETER (CDI_ZAXIS_VDIMNAME     = 803)
+      INTEGER    CDI_ZAXIS_LONGNAME    
+      PARAMETER (CDI_ZAXIS_LONGNAME     = 804)
+      INTEGER    CDI_ZAXIS_UNITS       
+      PARAMETER (CDI_ZAXIS_UNITS        = 805)
+      INTEGER         cdiZaxisDefString
+!                                    (INTEGER         zaxisID,
+!                                     INTEGER         key,
+!                                     INTEGER         size,
+!                                     CHARACTER*(*)   mesg)
+      EXTERNAL        cdiZaxisDefString
+
+      INTEGER         cdiZaxisInqString
+!                                    (INTEGER         zaxisID,
+!                                     INTEGER         key,
+!                                     INTEGER         size,
+!                                     CHARACTER*(*)   mesg)
+      EXTERNAL        cdiZaxisInqString
+
 !                     zaxisDefName
 !                                    (INTEGER         zaxisID,
 !                                     CHARACTER*(*)   name_optional)
diff --git a/libcdi/src/cdiFortran.c b/libcdi/src/cdiFortran.c
index e8fd509..2b83d70 100644
--- a/libcdi/src/cdiFortran.c
+++ b/libcdi/src/cdiFortran.c
@@ -324,6 +324,11 @@ FCALLSCSUB2 (gridDefXvals, GRIDDEFXVALS, griddefxvals, INT, DOUBLEV)
 FCALLSCFUN2 (INT, gridInqXvals, GRIDINQXVALS, gridinqxvals, INT, DOUBLEV)
 FCALLSCSUB2 (gridDefYvals, GRIDDEFYVALS, griddefyvals, INT, DOUBLEV)
 FCALLSCFUN2 (INT, gridInqYvals, GRIDINQYVALS, gridinqyvals, INT, DOUBLEV)
+
+/*  CDI grid string key values  */
+
+FCALLSCFUN4 (INT, cdiGridDefString, CDIGRIDDEFSTRING, cdigriddefstring, INT, INT, INT, STRING)
+FCALLSCFUN4 (INT, cdiGridInqString, CDIGRIDINQSTRING, cdigridinqstring, INT, INT, INT, PSTRING)
 FCALLSCSUB2 (gridDefXname, GRIDDEFXNAME, griddefxname, INT, STRING)
 FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING)
 FCALLSCSUB2 (gridDefXlongname, GRIDDEFXLONGNAME, griddefxlongname, INT, STRING)
@@ -426,6 +431,11 @@ FCALLSCSUB2 (zaxisDefNumber, ZAXISDEFNUMBER, zaxisdefnumber, INT, INT)
 FCALLSCFUN1 (INT, zaxisInqNumber, ZAXISINQNUMBER, zaxisinqnumber, INT)
 FCALLSCSUB2 (zaxisDefUUID, ZAXISDEFUUID, zaxisdefuuid, INT, PVOID)
 FCALLSCSUB2 (zaxisInqUUID, ZAXISINQUUID, zaxisinquuid, INT, PVOID)
+
+/*  CDI zaxis string key values  */
+
+FCALLSCFUN4 (INT, cdiZaxisDefString, CDIZAXISDEFSTRING, cdizaxisdefstring, INT, INT, INT, STRING)
+FCALLSCFUN4 (INT, cdiZaxisInqString, CDIZAXISINQSTRING, cdizaxisinqstring, INT, INT, INT, PSTRING)
 FCALLSCSUB2 (zaxisDefName, ZAXISDEFNAME, zaxisdefname, INT, STRING)
 FCALLSCSUB2 (zaxisInqName, ZAXISINQNAME, zaxisinqname, INT, PSTRING)
 FCALLSCSUB2 (zaxisDefLongname, ZAXISDEFLONGNAME, zaxisdeflongname, INT, STRING)
diff --git a/libcdi/src/cdi_int.c b/libcdi/src/cdi_int.c
index 954122c..5050709 100644
--- a/libcdi/src/cdi_int.c
+++ b/libcdi/src/cdi_int.c
@@ -132,7 +132,7 @@ void cdiPrintVersion(void)
 #if  defined  (HAVE_LIBNETCDF)
   fprintf(stderr, "  NetCDF library version : %s\n", cdfLibraryVersion());
 #endif
-#if  defined  (HAVE_LIBHDF5)
+#if  defined  (HAVE_NC4HDF5)
   fprintf(stderr, "    HDF5 library version : %s\n", hdfLibraryVersion());
 #endif
 #if  defined  (HAVE_LIBSERVICE)
diff --git a/libcdi/src/cdilib.c b/libcdi/src/cdilib.c
index 5220402..95fc3dd 100644
--- a/libcdi/src/cdilib.c
+++ b/libcdi/src/cdilib.c
@@ -1,7 +1,7 @@
 
-/* Automatically generated by m214003 at 2016-02-19, do not edit */
+/* Automatically generated by m214003 at 2016-04-18, do not edit */
 
-/* CDILIB_VERSION="1.7.1" */
+/* CDILIB_VERSION="1.7.2rc3" */
 
 #ifdef _ARCH_PWR6
 #pragma options nostrict
@@ -681,6 +681,8 @@ int     vlistInqVarZaxis(int vlistID, int varID);
 int     vlistInqVarID(int vlistID, int code);
 
 void    vlistDefVarTsteptype(int vlistID, int varID, int tsteptype);
+
+/*      vlistInqVarTsteptype: Get the timestep type of a Variable */
 int     vlistInqVarTsteptype(int vlistID, int varID);
 
 void    vlistDefVarCompType(int vlistID, int varID, int comptype);
@@ -896,6 +898,23 @@ void    gridDefYvals(int gridID, const double yvals[]);
 /*      gridInqYvals: Get all values of a Y-axis */
 int     gridInqYvals(int gridID, double yvals[]);
 
+/* CDI grid string key values */
+#define  CDI_GRID_XNAME      901  // X-axis name
+#define  CDI_GRID_YNAME      902  // Y-axis name
+#define  CDI_GRID_XDIMNAME   903  // X-axis dimension name
+#define  CDI_GRID_YDIMNAME   904  // Y-axis dimension name
+#define  CDI_GRID_VDIMNAME   905  // Vertex dimension name
+#define  CDI_GRID_XLONGNAME  906  // X-axis longname
+#define  CDI_GRID_YLONGNAME  907  // Y-axis longname
+#define  CDI_GRID_XUNITS     908  // X-axis units
+#define  CDI_GRID_YUNITS     909  // Y-axis units
+
+//      cdiGridDefString: Define a CDI grid string value from a key
+int     cdiGridDefString(int gridID, int key, int size, const char *mesg);
+
+//      cdiGridInqString: Get a CDI grid string value from a key
+int     cdiGridInqString(int gridID, int key, int size, char *mesg);
+
 /*      gridDefXname: Define the name of a X-axis */
 void    gridDefXname(int gridID, const char *xname);
 
@@ -1102,6 +1121,19 @@ void    zaxisDefUUID(int zaxisID, const unsigned char uuid[CDI_UUID_SIZE]);
 /*      zaxisInqUUID: Get the UUID of a generalized Z-axis */
 void    zaxisInqUUID(int zaxisID, unsigned char uuid[CDI_UUID_SIZE]);
 
+/* CDI zaxis string key values */
+#define  CDI_ZAXIS_NAME      801  // Z-axis name
+#define  CDI_ZAXIS_DIMNAME   802  // Z-axis dimension name
+#define  CDI_ZAXIS_VDIMNAME  803  // Vertex dimension name
+#define  CDI_ZAXIS_LONGNAME  804  // Z-axis longname
+#define  CDI_ZAXIS_UNITS     805  // Z-axis units
+
+//      cdiZaxisDefString: Define a CDI Z-axis string value from a key
+int     cdiZaxisDefString(int zaxisID, int key, int size, const char *mesg);
+
+//      cdiZaxisInqString: Get a CDI Z-axis string value from a key
+int     cdiZaxisInqString(int zaxisID, int key, int size, char *mesg);
+
 /*      zaxisDefName: Define the name of a Z-axis */
 void    zaxisDefName(int zaxisID, const char *name_optional);
 
@@ -1493,8 +1525,8 @@ void swap8byte(void *ptr, size_t size);
  * require-trailing-newline: t
  * End:
  */
-#ifndef _DTYPES_H
-#define _DTYPES_H
+#ifndef DTYPES_H
+#define DTYPES_H
 
 #include <stdio.h>
 #include <limits.h>
@@ -1540,7 +1572,7 @@ void swap8byte(void *ptr, size_t size);
 #define  UINT32   unsigned INT32
 #define  UINT64   unsigned INT64
 
-#endif  /* _DTYPES_H */
+#endif  /* DTYPES_H */
 /*
  * Local Variables:
  * c-file-style: "Java"
@@ -1559,8 +1591,6 @@ void swap8byte(void *ptr, size_t size);
 #include <inttypes.h>
 #include <stdio.h>
 
-#ifndef _DTYPES_H
-#endif
 
 #ifndef HOST_ENDIANNESS
 #ifdef __cplusplus
@@ -3280,14 +3310,14 @@ typedef void (*cdi_cdf_def_var_funcp)(int ncid, const char *name,
 const char *cdfLibraryVersion(void)
 {
 #if  defined  (HAVE_LIBNETCDF)
-  return (nc_inq_libvers());
+  return nc_inq_libvers();
 #else
-  return ("library undefined");
+  return "library undefined";
 #endif
 }
 
-#if  defined(HAVE_LIBHDF5)
-#if defined(__cplusplus)
+#if  defined(HAVE_H5GET_LIBVERSION)
+#if  defined(__cplusplus)
 extern "C" {
 #endif
   int H5get_libversion(unsigned *, unsigned *, unsigned *);
@@ -3298,17 +3328,20 @@ extern "C" {
 
 const char *hdfLibraryVersion(void)
 {
-#if  defined(HAVE_LIBHDF5)
+#if  defined(HAVE_H5GET_LIBVERSION)
   static char hdf_libvers[256];
   unsigned majnum, minnum, relnum;
 
   H5get_libversion(&majnum, &minnum, &relnum);
 
+#if  defined(HAVE_NC4HDF5_THREADSAFE)
+  sprintf(hdf_libvers, "%u.%u.%u threadsafe", majnum, minnum, relnum);
+#else
   sprintf(hdf_libvers, "%u.%u.%u", majnum, minnum, relnum);
-
-  return (hdf_libvers);
+#endif
+  return hdf_libvers;
 #else
-  return ("library undefined");
+  return "library undefined";
 #endif
 }
 
@@ -3400,24 +3433,23 @@ static int cdfOpenFile(const char *filename, const char *mode, int *filetype)
     }
 #endif
 
-  return (ncid);
+  return ncid;
 }
 
 
 int cdfOpen(const char *filename, const char *mode)
 {
-  int fileID = 0;
   int filetype = FILETYPE_NC;
 
   if ( CDF_Debug )
     Message("Open %s with mode %c", filename, *mode);
 
-  fileID = cdfOpenFile(filename, mode, &filetype);
+  int fileID = cdfOpenFile(filename, mode, &filetype);
 
   if ( CDF_Debug )
     Message("File %s opened with id %d", filename, fileID);
 
-  return (fileID);
+  return fileID;
 }
 
 
@@ -3448,7 +3480,7 @@ int cdfOpen64(const char *filename, const char *mode)
       fileID = CDI_ELIBNAVAIL;
     }
 
-  return (fileID);
+  return fileID;
 }
 
 
@@ -3476,7 +3508,7 @@ int cdf4Open(const char *filename, const char *mode, int *filetype)
       fileID = CDI_ELIBNAVAIL;
     }
 
-  return (fileID);
+  return fileID;
 }
 
 
@@ -5160,7 +5192,7 @@ void cdiPrintVersion(void)
 #if  defined  (HAVE_LIBNETCDF)
   fprintf(stderr, "  NetCDF library version : %s\n", cdfLibraryVersion());
 #endif
-#if  defined  (HAVE_LIBHDF5)
+#if  defined  (HAVE_NC4HDF5)
   fprintf(stderr, "    HDF5 library version : %s\n", hdfLibraryVersion());
 #endif
 #if  defined  (HAVE_LIBSERVICE)
@@ -22962,6 +22994,9 @@ struct grid_t {
   short   hasdims;
   const char *xstdname;
   const char *ystdname;
+  char    xdimname[CDI_MAX_NAME];
+  char    ydimname[CDI_MAX_NAME];
+  char    vdimname[CDI_MAX_NAME];
   char    xname[CDI_MAX_NAME];
   char    yname[CDI_MAX_NAME];
   char    xlongname[CDI_MAX_NAME];
@@ -22990,6 +23025,11 @@ const double *gridInqXboundsPtr(int gridID);
 const double *gridInqYboundsPtr(int gridID);
 const double *gridInqAreaPtr(int gridID);
 
+const char *gridInqXnamePtr(int gridID);
+const char *gridInqYnamePtr(int gridID);
+
+const char *gridInqReferencePtr(int gridID);
+
 int gridCompare(int gridID, const grid_t *grid);
 int gridGenerate(const grid_t *grid);
 
@@ -23530,27 +23570,24 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     case GRID_LONLAT:
     case GRID_GAUSSIAN:
       {
-        long lpar;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &lpar);
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        int nlon = (int)lpar;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &lpar);
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        int nlat = (int)lpar;
+        long nlon, nlat;
+        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &nlon);
+        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &nlat);
 
         if ( gridtype == GRID_GAUSSIAN )
           {
+            long lpar;
             FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar);
             grid->np = (int)lpar;
           }
 
         if ( numberOfPoints != nlon*nlat )
-          Error("numberOfPoints (%ld) and gridSize (%d) differ!", numberOfPoints, nlon*nlat);
+          Error("numberOfPoints (%ld) and gridSize (%ld) differ!", numberOfPoints, nlon*nlat);
 
         /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
         grid->size  = (int)numberOfPoints;
-        grid->xsize = nlon;
-        grid->ysize = nlat;
+        grid->xsize = (int)nlon;
+        grid->ysize = (int)nlat;
         grid->xinc  = 0;
         grid->yinc  = 0;
         grid->xdef  = 0;
@@ -23558,13 +23595,16 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
-        if ( gridtype == GRID_LONLAT )
+        if ( nlon > 1 )
+          FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
+        if ( gridtype == GRID_LONLAT && nlat > 1 )
           FAIL_ON_GRIB_ERROR(grib_get_double, gh, "jDirectionIncrementInDegrees", &grid->yinc);
 
         if ( grid->xinc < -999 || grid->xinc > 999 ) grid->xinc = 0;
         if ( grid->yinc < -999 || grid->yinc > 999 ) grid->yinc = 0;
 
+        if ( grid->yinc > 0 && grid->yfirst > grid->ylast ) grid->yinc = -grid->yinc;
+
         /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
           {
             if ( grid->xsize > 1 )
@@ -23634,9 +23674,9 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
 
-        if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0;
+        // FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
+        // if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0;
 
         /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
           {
@@ -24235,79 +24275,82 @@ grid_t *gridID2Ptr(int gridID)
 
 void grid_init(grid_t *gridptr)
 {
-  gridptr->self         = CDI_UNDEFID;
-  gridptr->type         = CDI_UNDEFID;
-  gridptr->proj         = CDI_UNDEFID;
-  gridptr->mask         = NULL;
-  gridptr->mask_gme     = NULL;
-  gridptr->xvals        = NULL;
-  gridptr->yvals        = NULL;
-  gridptr->area         = NULL;
-  gridptr->xbounds      = NULL;
-  gridptr->ybounds      = NULL;
-  gridptr->rowlon       = NULL;
-  gridptr->nrowlon      = 0;
-  gridptr->xfirst       = 0.0;
-  gridptr->xlast        = 0.0;
-  gridptr->xinc         = 0.0;
-  gridptr->yfirst       = 0.0;
-  gridptr->ylast        = 0.0;
-  gridptr->yinc         = 0.0;
+  gridptr->self          = CDI_UNDEFID;
+  gridptr->type          = CDI_UNDEFID;
+  gridptr->proj          = CDI_UNDEFID;
+  gridptr->mask          = NULL;
+  gridptr->mask_gme      = NULL;
+  gridptr->xvals         = NULL;
+  gridptr->yvals         = NULL;
+  gridptr->area          = NULL;
+  gridptr->xbounds       = NULL;
+  gridptr->ybounds       = NULL;
+  gridptr->rowlon        = NULL;
+  gridptr->nrowlon       = 0;
+  gridptr->xfirst        = 0.0;
+  gridptr->xlast         = 0.0;
+  gridptr->xinc          = 0.0;
+  gridptr->yfirst        = 0.0;
+  gridptr->ylast         = 0.0;
+  gridptr->yinc          = 0.0;
   gridptr->lcc_originLon = 0.0;
   gridptr->lcc_originLat = 0.0;
-  gridptr->lcc_lonParY  = 0.0;
-  gridptr->lcc_lat1     = 0.0;
-  gridptr->lcc_lat2     = 0.0;
-  gridptr->lcc_xinc     = 0.0;
-  gridptr->lcc_yinc     = 0.0;
-  gridptr->lcc_projflag = 0;
-  gridptr->lcc_scanflag = 0;
-  gridptr->lcc_defined  = FALSE;
-  gridptr->lcc2_lon_0   = 0.0;
-  gridptr->lcc2_lat_0   = 0.0;
-  gridptr->lcc2_lat_1   = 0.0;
-  gridptr->lcc2_lat_2   = 0.0;
-  gridptr->lcc2_a       = 0.0;
-  gridptr->lcc2_defined = FALSE;
-  gridptr->laea_lon_0   = 0.0;
-  gridptr->laea_lat_0   = 0.0;
-  gridptr->laea_a       = 0.0;
-  gridptr->laea_defined = FALSE;
-  gridptr->trunc        = 0;
-  gridptr->nvertex      = 0;
-  gridptr->nd           = 0;
-  gridptr->ni           = 0;
-  gridptr->ni2          = 0;
-  gridptr->ni3          = 0;
-  gridptr->number       = 0;
-  gridptr->position     = 0;
-  gridptr->reference    = NULL;
-  gridptr->prec         = 0;
-  gridptr->size         = 0;
-  gridptr->xsize        = 0;
-  gridptr->ysize        = 0;
-  gridptr->np           = 0;
-  gridptr->xdef         = 0;
-  gridptr->ydef         = 0;
-  gridptr->isCyclic     = CDI_UNDEFID;
-  gridptr->isRotated    = FALSE;
-  gridptr->xpole        = 0.0;
-  gridptr->ypole        = 0.0;
-  gridptr->angle        = 0.0;
-  gridptr->lcomplex     = 0;
-  gridptr->hasdims      = TRUE;
-  gridptr->xname[0]     = 0;
-  gridptr->yname[0]     = 0;
-  gridptr->xlongname[0] = 0;
-  gridptr->ylongname[0] = 0;
-  gridptr->xunits[0]    = 0;
-  gridptr->yunits[0]    = 0;
-  gridptr->xstdname  = NULL;
-  gridptr->ystdname  = NULL;
+  gridptr->lcc_lonParY   = 0.0;
+  gridptr->lcc_lat1      = 0.0;
+  gridptr->lcc_lat2      = 0.0;
+  gridptr->lcc_xinc      = 0.0;
+  gridptr->lcc_yinc      = 0.0;
+  gridptr->lcc_projflag  = 0;
+  gridptr->lcc_scanflag  = 0;
+  gridptr->lcc_defined   = FALSE;
+  gridptr->lcc2_lon_0    = 0.0;
+  gridptr->lcc2_lat_0    = 0.0;
+  gridptr->lcc2_lat_1    = 0.0;
+  gridptr->lcc2_lat_2    = 0.0;
+  gridptr->lcc2_a        = 0.0;
+  gridptr->lcc2_defined  = FALSE;
+  gridptr->laea_lon_0    = 0.0;
+  gridptr->laea_lat_0    = 0.0;
+  gridptr->laea_a        = 0.0;
+  gridptr->laea_defined  = FALSE;
+  gridptr->trunc         = 0;
+  gridptr->nvertex       = 0;
+  gridptr->nd            = 0;
+  gridptr->ni            = 0;
+  gridptr->ni2           = 0;
+  gridptr->ni3           = 0;
+  gridptr->number        = 0;
+  gridptr->position      = 0;
+  gridptr->reference     = NULL;
+  gridptr->prec          = 0;
+  gridptr->size          = 0;
+  gridptr->xsize         = 0;
+  gridptr->ysize         = 0;
+  gridptr->np            = 0;
+  gridptr->xdef          = 0;
+  gridptr->ydef          = 0;
+  gridptr->isCyclic      = CDI_UNDEFID;
+  gridptr->isRotated     = FALSE;
+  gridptr->xpole         = 0.0;
+  gridptr->ypole         = 0.0;
+  gridptr->angle         = 0.0;
+  gridptr->lcomplex      = 0;
+  gridptr->hasdims       = TRUE;
+  gridptr->xdimname[0]   = 0;
+  gridptr->ydimname[0]   = 0;
+  gridptr->vdimname[0]   = 0;
+  gridptr->xname[0]      = 0;
+  gridptr->yname[0]      = 0;
+  gridptr->xlongname[0]  = 0;
+  gridptr->ylongname[0]  = 0;
+  gridptr->xunits[0]     = 0;
+  gridptr->yunits[0]     = 0;
+  gridptr->xstdname      = NULL;
+  gridptr->ystdname      = NULL;
   memset(gridptr->uuid, 0, CDI_UUID_SIZE);
-  gridptr->name         = NULL;
-  gridptr->vtable       = &cdiGridVtable;
-  gridptr->extraData    = NULL;
+  gridptr->name          = NULL;
+  gridptr->vtable        = &cdiGridVtable;
+  gridptr->extraData     = NULL;
 }
 
 
@@ -24382,52 +24425,32 @@ unsigned cdiGridCount(void)
   return reshCountType(&gridOps);
 }
 
-static inline void
-gridSetXname(grid_t *gridptr, const char *xname)
-{
-  strncpy(gridptr->xname, xname, CDI_MAX_NAME);
-  gridptr->xname[CDI_MAX_NAME - 1] = 0;
-}
-
-static inline void
-gridSetXlongname(grid_t *gridptr, const char *xlongname)
-{
-  strncpy(gridptr->xlongname, xlongname, CDI_MAX_NAME);
-  gridptr->xlongname[CDI_MAX_NAME - 1] = 0;
-}
-
-static inline void
-gridSetXunits(grid_t *gridptr, const char *xunits)
-{
-  strncpy(gridptr->xunits, xunits, CDI_MAX_NAME);
-  gridptr->xunits[CDI_MAX_NAME - 1] = 0;
-}
-
-static inline void
-gridSetYname(grid_t *gridptr, const char *yname)
+static inline
+void gridSetString(char *gridstrname, const char *name, size_t len)
 {
-  strncpy(gridptr->yname, yname, CDI_MAX_NAME);
-  gridptr->yname[CDI_MAX_NAME - 1] = 0;
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(gridstrname, name, len);
+  gridstrname[len - 1] = 0;
 }
 
-static inline void
-gridSetYlongname(grid_t *gridptr, const char *ylongname)
+static inline
+void gridGetString(char *name, const char *gridstrname, size_t len)
 {
-  strncpy(gridptr->ylongname, ylongname, CDI_MAX_NAME);
-  gridptr->ylongname[CDI_MAX_NAME - 1] = 0;
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(name, gridstrname, len);
+  name[len - 1] = 0;
 }
 
 static inline void
-gridSetYunits(grid_t *gridptr, const char *yunits)
+gridSetName(char *gridstrname, const char *name)
 {
-  strncpy(gridptr->yunits, yunits, CDI_MAX_NAME);
-  gridptr->yunits[CDI_MAX_NAME - 1] = 0;
+  strncpy(gridstrname, name, CDI_MAX_NAME);
+  gridstrname[CDI_MAX_NAME - 1] = 0;
 }
 
 void
 cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
 {
-
   gridptr->type = gridtype;
   gridptr->size = size;
 
@@ -24443,16 +24466,16 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
       {
         if ( gridtype == GRID_TRAJECTORY )
           {
-            gridSetXname(gridptr, "tlon");
-            gridSetYname(gridptr, "tlat");
+            if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "tlon");
+            if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "tlat");
           }
         else
           {
-            gridSetXname(gridptr, "lon");
-            gridSetYname(gridptr, "lat");
+            if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon");
+            if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat");
           }
-        gridSetXlongname(gridptr, "longitude");
-        gridSetYlongname(gridptr, "latitude");
+        gridSetName(gridptr->xlongname, "longitude");
+        gridSetName(gridptr->ylongname, "latitude");
 
         /*
         if ( gridtype == GRID_CURVILINEAR )
@@ -24467,8 +24490,8 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
           {
             gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
             gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
-            gridSetXunits(gridptr, "degrees_east");
-            gridSetYunits(gridptr, "degrees_north");
+            gridSetName(gridptr->xunits, "degrees_east");
+            gridSetName(gridptr->yunits, "degrees_north");
           }
 
         break;
@@ -24478,20 +24501,20 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
       /* Fall through */
     case GRID_GME:
       {
-        gridSetXname(gridptr, "lon");
-        gridSetYname(gridptr, "lat");
+        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon");
+        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat");
         gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
         gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
-        gridSetXunits(gridptr, "degrees_east");
-        gridSetYunits(gridptr, "degrees_north");
+        gridSetName(gridptr->xunits, "degrees_east");
+        gridSetName(gridptr->yunits, "degrees_north");
         break;
       }
     case GRID_GENERIC:
       {
 
         /* gridptr->xsize = size; */
-        gridSetXname(gridptr, "x");
-        gridSetYname(gridptr, "y");
+        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x");
+        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y");
         /*
         strcpy(gridptr->xstdname, "grid_longitude");
         strcpy(gridptr->ystdname, "grid_latitude");
@@ -24506,16 +24529,15 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
     case GRID_SINUSOIDAL:
     case GRID_LAEA:
       {
-        gridSetXname(gridptr, "x");
-        gridSetYname(gridptr, "y");
+        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x");
+        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y");
         gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0];
         gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1];
-        gridSetXunits(gridptr, "m");
-        gridSetYunits(gridptr, "m");
+        gridSetName(gridptr->xunits, "m");
+        gridSetName(gridptr->yunits, "m");
         break;
       }
     }
-
 }
 
 
@@ -24660,7 +24682,7 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
     @Item  gridtype  The type of the grid, one of the set of predefined CDI grid types.
                      The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
                      @func{GRID_LONLAT}, @func{GRID_LCC}, @func{GRID_SPECTRAL},
-                     @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED} and.
+                     @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
     @Item  size      Number of gridpoints.
 
 @Description
@@ -24762,6 +24784,98 @@ void gridName(int gridtype, char *gridname)
   strcpy(gridname, gridNamePtr(gridtype));
 }
 
+static
+char *grid_key_to_string(grid_t *gridptr, int key)
+{
+  char *gridstring = NULL;
+
+  switch (key)
+    {
+    case CDI_GRID_XDIMNAME: gridstring = gridptr->xdimname; break;
+    case CDI_GRID_YDIMNAME: gridstring = gridptr->ydimname; break;
+    case CDI_GRID_VDIMNAME: gridstring = gridptr->vdimname; break;
+    }
+
+  return gridstring;
+}
+
+/*
+ at Function  cdiGridDefString
+ at Title     Define a CDI grid string value from a key
+
+ at Prototype int cdiGridDefString(int gridID, int key, int size, const char *mesg)
+ at Parameter
+    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
+    @Item  key      The key to be searched
+    @Item  size     The allocated length of the string on input
+    @Item  mesg     The address of a string where the data will be read
+
+ at Description
+The function @func{cdiGridDefString} defines a CDI grid string value from a key.
+
+ at Result
+ at func{cdiGridDefString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiGridDefString(int gridID, int key, int size, const char *mesg)
+{
+  if ( size < 1 || mesg == NULL || *mesg == 0 ) return -1;
+
+  grid_t *gridptr = gridID2Ptr(gridID);
+
+  char *gridstring = grid_key_to_string(gridptr, key);
+  if ( gridstring == NULL)
+    {
+      Warning("CDI grid string key %d not supported!", key);
+      return -1;
+    }
+
+  gridSetString(gridstring, mesg, (size_t)size);
+  gridMark4Update(gridID);
+
+  return 0;
+}
+
+/*
+ at Function  cdiGridInqString
+ at Title     Get a CDI grid string value from a key
+
+ at Prototype int cdiGridInqString(int gridID, int key, int size, char *mesg)
+ at Parameter
+    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
+    @Item  key      The key to be searched.
+    @Item  size     The allocated length of the string on input.
+    @Item  mesg     The address of a string where the data will be retrieved.
+                    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}.
+
+ at Description
+The function @func{cdiGridInqString} return a CDI grid string value from a key.
+
+ at Result
+ at func{cdiGridInqString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiGridInqString(int gridID, int key, int size, char *mesg)
+{
+  if ( size < 1 || mesg == NULL ) return -1;
+
+  grid_t *gridptr = gridID2Ptr(gridID);
+  const char *gridstring = grid_key_to_string(gridptr, key);
+  if ( gridstring == NULL)
+    {
+      Warning("CDI grid string key %d not supported!", key);
+      return -1;
+    }
+
+  gridGetString(mesg, gridstring, (size_t)size);
+
+  return 0;
+}
+
 /*
 @Function  gridDefXname
 @Title     Define the name of a X-axis
@@ -24781,12 +24895,11 @@ void gridDefXname(int gridID, const char *xname)
   if ( xname && *xname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetXname(gridptr, xname);
+      gridSetName(gridptr->xname, xname);
       gridMark4Update(gridID);
     }
 }
 
-
 /*
 @Function  gridDefXlongname
 @Title     Define the longname of a X-axis
@@ -24806,7 +24919,7 @@ void gridDefXlongname(int gridID, const char *xlongname)
   if ( xlongname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetXlongname(gridptr, xlongname);
+      gridSetName(gridptr->xlongname, xlongname);
       gridMark4Update(gridID);
     }
 }
@@ -24830,7 +24943,7 @@ void gridDefXunits(int gridID, const char *xunits)
   if ( xunits )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetXunits(gridptr, xunits);
+      gridSetName(gridptr->xunits, xunits);
       gridMark4Update(gridID);
     }
 }
@@ -24854,7 +24967,7 @@ void gridDefYname(int gridID, const char *yname)
   if ( yname && *yname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetYname(gridptr, yname);
+      gridSetName(gridptr->yname, yname);
       gridMark4Update(gridID);
     }
 }
@@ -24878,7 +24991,7 @@ void gridDefYlongname(int gridID, const char *ylongname)
   if ( ylongname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetYlongname(gridptr, ylongname);
+      gridSetName(gridptr->ylongname, ylongname);
       gridMark4Update(gridID);
     }
 }
@@ -24902,7 +25015,7 @@ void gridDefYunits(int gridID, const char *yunits)
   if ( yunits )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetYunits(gridptr, yunits);
+      gridSetName(gridptr->yunits, yunits);
       gridMark4Update(gridID);
     }
 }
@@ -24933,6 +25046,12 @@ void gridInqXname(int gridID, char *xname)
   strcpy(xname, gridptr->xname);
 }
 
+const char *gridInqXnamePtr(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  return gridptr->xname;
+}
+
 /*
 @Function  gridInqXlongname
 @Title     Get the longname of a X-axis
@@ -25021,6 +25140,12 @@ void gridInqYname(int gridID, char *yname)
   strcpy(yname, gridptr->yname);
 }
 
+const char *gridInqYnamePtr(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  return gridptr->yname;
+}
+
 /*
 @Function  gridInqYlongname
 @Title     Get the longname of a Y-axis
@@ -26553,8 +26678,8 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
   else if ( g2_xvals )
     return differ;
 
-  const double *restrict g1_yvals = g1->vtable->inqXValsPtr(g1),
-    *restrict g2_yvals = g2->vtable->inqXValsPtr(g2);
+  const double *restrict g1_yvals = g1->vtable->inqYValsPtr(g1),
+    *restrict g2_yvals = g2->vtable->inqYValsPtr(g2);
   if ( g1_yvals )
     {
       if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
@@ -26840,7 +26965,8 @@ static void gridComplete(grid_t *grid)
 
 }
 
-#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
+#define GRID_STR_SERIALIZE(gridP) { gridP->xdimname, gridP->ydimname,  \
+    gridP->vdimname, gridP->xname, gridP->yname,  \
     gridP->xlongname, gridP->ylongname, \
     gridP->xunits, gridP->yunits }
 
@@ -28167,15 +28293,23 @@ The function @func{gridInqReference} returns the reference URI to an unstructure
 */
 int gridInqReference(int gridID, char *reference)
 {
-  int len = 0;
+  size_t len = 0;
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->reference && reference )
+  if ( gridptr->reference )
     {
-      strcpy(reference, gridptr->reference);
+      len = strlen(gridptr->reference);
+      if ( reference )
+        strcpy(reference, gridptr->reference);
     }
 
-  return (len);
+  return (int)len;
+}
+
+const char *gridInqReferencePtr(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  return gridptr->reference;
 }
 
 /*
@@ -28269,11 +28403,6 @@ static int gridGetComponentFlags(const grid_t * gridP)
   return flags;
 }
 
-
-#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
-    gridP->xlongname, gridP->ylongname, \
-    gridP->xunits, gridP->yunits }
-
 static int
 gridGetPackSize(void * voidP, void *context)
 {
@@ -31847,6 +31976,8 @@ void zaxisDefLtype2(int zaxisID, int ltype2);
 
 const resOps *getZaxisOps(void);
 
+const char *zaxisInqNamePtr(int zaxisID);
+
 #endif
 
 /*
@@ -37794,7 +37925,7 @@ int  zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, const do
 #undef  UNDEFID
 #define UNDEFID  CDI_UNDEFID
 
-#define  BNDS_NAME  "bnds"
+static const char bndsName[] = "bnds";
 
 #define  X_AXIS  1
 #define  Y_AXIS  2
@@ -37843,6 +37974,7 @@ typedef struct {
   int      zvarid;
   int      tvarid;
   int      psvarid;
+  int      p0varid;
   int      ncoordvars;
   int      coordvarids[MAX_COORDVARS];
   int      nauxvars;
@@ -37918,33 +38050,27 @@ int get_timeunit(size_t len, const char *ptu)
 static
 bool isTimeUnits(const char *timeunits)
 {
-  bool status = false;
-
-  if ( strncmp(timeunits, "sec",    3) == 0 ||
-       strncmp(timeunits, "minute", 6) == 0 ||
-       strncmp(timeunits, "hour",   4) == 0 ||
-       strncmp(timeunits, "day",    3) == 0 ||
-       strncmp(timeunits, "month",  5) == 0 ) status = true;
-
+  bool status = strncmp(timeunits, "sec",    3) == 0
+    || strncmp(timeunits, "minute", 6) == 0
+    || strncmp(timeunits, "hour",   4) == 0
+    || strncmp(timeunits, "day",    3) == 0
+    || strncmp(timeunits, "month",  5) == 0;
   return status;
 }
 
 static
 bool isTimeAxisUnits(const char *timeunits)
 {
-  char *ptu, *tu;
-  int timetype = -1;
-  int timeunit;
   bool status = false;
 
   size_t len = strlen(timeunits);
-  tu = (char *) Malloc((len+1)*sizeof(char));
+  char *tu = (char *) Malloc((len+1)*sizeof(char));
   memcpy(tu, timeunits, (len+1) * sizeof(char));
-  ptu = tu;
+  char *ptu = tu;
 
   for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
 
-  timeunit = get_timeunit(len, ptu);
+  int timeunit = get_timeunit(len, ptu);
   if ( timeunit != -1 )
     {
 
@@ -37953,12 +38079,10 @@ bool isTimeAxisUnits(const char *timeunits)
         {
           while ( isspace(*ptu) ) ptu++;
 
-          if ( memcmp(ptu, "as", 2) == 0 )
-            timetype = TAXIS_ABSOLUTE;
-          else if ( memcmp(ptu, "since", 5) == 0 )
-            timetype = TAXIS_RELATIVE;
+          int timetype = memcmp(ptu, "as", 2) == 0 ? TAXIS_ABSOLUTE :
+            memcmp(ptu, "since", 5) == 0 ? TAXIS_RELATIVE : -1;
 
-          if ( timetype != -1 ) status = true;
+          status = timetype != -1;
         }
     }
 
@@ -38136,12 +38260,8 @@ void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int
 
   if ( atttype != NC_CHAR )
     {
-      int *pintatt = NULL;
-
-      if ( (int)nc_attlen > attlen )
-        pintatt = (int *) Malloc(nc_attlen * sizeof (int));
-      else
-        pintatt = attint;
+      int *pintatt = (int)nc_attlen > attlen
+        ? (int *)(Malloc(nc_attlen * sizeof (int))) : attint;
 
       cdf_get_att_int(fileID, ncvarid, attname, pintatt);
 
@@ -38250,10 +38370,7 @@ int xtypeIsText(int xtype)
 static
 int xtypeIsFloat(int xtype)
 {
-  int isFloat = FALSE;
-
-  if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
-
+  int isFloat = xtype == NC_FLOAT || xtype == NC_DOUBLE;
   return isFloat;
 }
 
@@ -38287,7 +38404,6 @@ int cdfInqDatatype(int xtype, int lunsigned)
 
 void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int memtype  = MEMTYPE_DOUBLE;
   int vlistID1 = streamptr1->vlistID;
   int tsID     = streamptr1->curTsID;
   int vrecID   = streamptr1->tsteps[tsID].curRecID;
@@ -38296,14 +38412,11 @@ void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
   int gridID   = vlistInqVarGrid(vlistID1, ivarID);
   int datasize = gridInqSize(gridID);
   int datatype = vlistInqVarDatatype(vlistID1, ivarID);
+  int memtype  = datatype != DATATYPE_FLT32 ? MEMTYPE_DOUBLE : MEMTYPE_FLOAT;
 
-  if ( datatype == DATATYPE_FLT32 ) memtype = MEMTYPE_FLOAT;
-
-  void *data = NULL;
-  if ( memtype == MEMTYPE_DOUBLE )
-    data = Malloc((size_t)datasize*sizeof(double));
-  else
-    data = Malloc((size_t)datasize*sizeof(float));
+  void *data
+    = Malloc((size_t)datasize
+             * (memtype == MEMTYPE_DOUBLE ? sizeof(double) : sizeof(float)));
 
   int nmiss;
   cdf_read_record(streamptr1, memtype, data, &nmiss);
@@ -38424,36 +38537,43 @@ printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
 }
 
 static
-int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, char* taxis_name, taxis_t* taxis)
+int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *taxis_name, taxis_t* taxis)
 {
   int time_bndsid = -1;
   int dims[2];
-  char tmpstr[CDI_MAX_NAME];
 
   dims[0] = nctimedimid;
 
   /* fprintf(stderr, "time has bounds\n"); */
 
-  if ( nc_inq_dimid(fileID, BNDS_NAME, &dims[1]) != NC_NOERR )
-    cdf_def_dim(fileID, BNDS_NAME, 2, &dims[1]);
+  if ( nc_inq_dimid(fileID, bndsName, &dims[1]) != NC_NOERR )
+    cdf_def_dim(fileID, bndsName, 2, &dims[1]);
 
+  const char *bndsAttName, *bndsAttVal;
+  size_t bndsAttValLen;
+  char tmpstr[CDI_MAX_NAME];
   if ( taxis->climatology )
     {
-      strcpy(tmpstr, "climatology_");
-      strcat(tmpstr, BNDS_NAME);
-      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
-
-      cdf_put_att_text(fileID, nctimevarid, "climatology", strlen(tmpstr), tmpstr);
+      static const char climatology_bndsName[] = "climatology_bnds",
+        climatology_bndsAttName[] = "climatology";
+      bndsAttName = climatology_bndsAttName;
+      bndsAttValLen = sizeof (climatology_bndsName) - 1;
+      bndsAttVal = climatology_bndsName;
     }
   else
     {
-      strcpy(tmpstr, taxis_name);
-      strcat(tmpstr, "_");
-      strcat(tmpstr, BNDS_NAME);
-      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
-
-      cdf_put_att_text(fileID, nctimevarid, "bounds", strlen(tmpstr), tmpstr);
+      size_t taxisnameLen = strlen(taxis_name);
+      memcpy(tmpstr, taxis_name, taxisnameLen);
+      tmpstr[taxisnameLen] = '_';
+      memcpy(tmpstr + taxisnameLen + 1, bndsName, sizeof (bndsName));
+      size_t tmpstrLen = taxisnameLen + sizeof (bndsName);
+      static const char generic_bndsAttName[] = "bounds";
+      bndsAttName = generic_bndsAttName;
+      bndsAttValLen = tmpstrLen;
+      bndsAttVal = tmpstr;
     }
+  cdf_def_var(fileID, bndsAttVal, NC_DOUBLE, 2, dims, &time_bndsid);
+  cdf_put_att_text(fileID, nctimevarid, bndsAttName, bndsAttValLen, bndsAttVal);
 
   return (time_bndsid);
 }
@@ -38474,8 +38594,7 @@ void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
     }
   else
     {
-      int timeunit = taxis->unit;
-      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
+      int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR;
       int rdate    = taxis->rdate;
       int rtime    = taxis->rtime;
       if ( rdate == -1 )
@@ -38512,27 +38631,30 @@ void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
        timeunit == TUNIT_6HOURS  ||
        timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
 
-  sprintf(unitstr, "%s", tunitNamePtr(timeunit));
+  strcpy(unitstr, tunitNamePtr(timeunit));
 }
 
 static
 void cdfDefCalendar(int fileID, int ncvarid, int calendar)
 {
-  size_t len;
-  char calstr[80];
-
-  calstr[0] = 0;
-
-  if      ( calendar == CALENDAR_STANDARD )  strcpy(calstr, "standard");
-  else if ( calendar == CALENDAR_PROLEPTIC ) strcpy(calstr, "proleptic_gregorian");
-  else if ( calendar == CALENDAR_NONE )      strcpy(calstr, "none");
-  else if ( calendar == CALENDAR_360DAYS )   strcpy(calstr, "360_day");
-  else if ( calendar == CALENDAR_365DAYS )   strcpy(calstr, "365_day");
-  else if ( calendar == CALENDAR_366DAYS )   strcpy(calstr, "366_day");
-
-  len = strlen(calstr);
+  static const struct { int calCode; const char *calStr; } calTab[] = {
+    { CALENDAR_STANDARD, "standard" },
+    { CALENDAR_PROLEPTIC, "proleptic_gregorian" },
+    { CALENDAR_NONE, "none" },
+    { CALENDAR_360DAYS, "360_day" },
+    { CALENDAR_365DAYS, "365_day" },
+    { CALENDAR_366DAYS, "366_day" },
+  };
+  enum { calTabSize = sizeof calTab / sizeof calTab[0] };
 
-  if ( len ) cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
+  for (size_t i = 0; i < calTabSize; ++i)
+    if (calTab[i].calCode == calendar)
+      {
+        const char *calstr = calTab[i].calStr;
+        size_t len = strlen(calstr);
+        cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
+        break;
+      }
 }
 
 
@@ -38541,10 +38663,7 @@ void cdfDefTime(stream_t* streamptr)
   int time_varid;
   int time_dimid;
   int time_bndsid = -1;
-  char unitstr[CDI_MAX_NAME];
-  char tmpstr[CDI_MAX_NAME];
-  char default_name[] = "time";
-  char* taxis_name = default_name;
+  static const char default_name[] = "time";
 
   if ( streamptr->basetime.ncvarid != UNDEFID ) return;
 
@@ -38555,7 +38674,7 @@ void cdfDefTime(stream_t* streamptr)
 
   taxis_t *taxis = &streamptr->tsteps[0].taxis;
 
-  if ( taxis->name && taxis->name[0] ) taxis_name = taxis->name;
+  const char *taxis_name = (taxis->name && taxis->name[0]) ? taxis->name : default_name ;
 
   cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
   streamptr->basetime.ncdimid = time_dimid;
@@ -38564,8 +38683,10 @@ void cdfDefTime(stream_t* streamptr)
 
   streamptr->basetime.ncvarid = time_varid;
 
-  strcpy(tmpstr, "time");
-  cdf_put_att_text(fileID, time_varid, "standard_name", strlen(tmpstr), tmpstr);
+  {
+    static const char timeStr[] = "time";
+    cdf_put_att_text(fileID, time_varid, "standard_name", sizeof(timeStr) - 1, timeStr);
+  }
 
   if ( taxis->longname && taxis->longname[0] )
     cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname);
@@ -38576,17 +38697,19 @@ void cdfDefTime(stream_t* streamptr)
       streamptr->basetime.ncvarboundsid = time_bndsid;
     }
 
-  cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
-
-  size_t len = strlen(unitstr);
-  if ( len )
-    {
-      cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
-      /*
-      if ( taxis->has_bounds )
-        cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
-      */
-    }
+  {
+    char unitstr[CDI_MAX_NAME];
+    cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
+    size_t len = strlen(unitstr);
+    if ( len )
+      {
+        cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
+        /*
+          if ( taxis->has_bounds )
+          cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
+        */
+      }
+  }
 
   if ( taxis->calendar != -1 )
     {
@@ -38605,16 +38728,23 @@ void cdfDefTime(stream_t* streamptr)
 
       streamptr->basetime.leadtimeid = leadtimeid;
 
-      strcpy(tmpstr, "forecast_period");
-      cdf_put_att_text(fileID, leadtimeid, "standard_name", strlen(tmpstr), tmpstr);
-
-      strcpy(tmpstr, "Time elapsed since the start of the forecast");
-      cdf_put_att_text(fileID, leadtimeid, "long_name", strlen(tmpstr), tmpstr);
+      {
+        static const char stdname[] = "forecast_period";
+        cdf_put_att_text(fileID, leadtimeid, "standard_name", sizeof(stdname) - 1, stdname);
+      }
 
-      cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);
+      {
+        static const char lname[] = "Time elapsed since the start of the forecast";
+        cdf_put_att_text(fileID, leadtimeid, "long_name", sizeof(lname) - 1, lname);
+      }
 
-      len = strlen(unitstr);
-      if ( len ) cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
+      {
+          char unitstr[CDI_MAX_NAME];
+          cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);
+          size_t len = strlen(unitstr);
+          if ( len )
+            cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
+      }
     }
 
   cdf_put_att_text(fileID, time_varid, "axis", 1, "T");
@@ -38635,7 +38765,7 @@ void cdfDefTimestep(stream_t *streamptr, int tsID)
 static
 void cdfDefComplex(stream_t *streamptr, int gridID)
 {
-  char axisname[] = "nc2";
+  static const char axisname[] = "nc2";
   int dimID = UNDEFID;
   int vlistID = streamptr->vlistID;
   int fileID  = streamptr->fileID;
@@ -38672,19 +38802,14 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
   streamptr->xdimID[gridindex] = dimID;
 }
 
-
-static
-void cdfDefSP(stream_t *streamptr, int gridID)
+static void
+cdfDefSPorFC(stream_t *streamptr, int gridID,
+             char *restrict axisname, int gridRefType)
 {
-  /*
-  char longname[] = "Spherical harmonic coefficient";
-  */
-  char axisname[5] = "nspX";
   int index, iz = 0;
   int dimID = UNDEFID;
 
   int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
 
   int ngrids = vlistNgrids(vlistID);
 
@@ -38696,7 +38821,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
         {
           int gridID0 = vlistGrid(vlistID, index);
           int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_SPECTRAL )
+          if ( gridtype0 == gridRefType )
             {
               size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
               if ( dimlen == dimlen0 )
@@ -38712,6 +38837,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
+      int fileID  = streamptr->fileID;
       if ( iz == 0 ) axisname[3] = '\0';
       else           sprintf(&axisname[3], "%1d", iz+1);
 
@@ -38727,76 +38853,94 @@ void cdfDefSP(stream_t *streamptr, int gridID)
   streamptr->ydimID[gridindex] = dimID;
 }
 
+static
+void cdfDefSP(stream_t *streamptr, int gridID)
+{
+  /*
+  char longname[] = "Spherical harmonic coefficient";
+  */
+  char axisname[5] = "nspX";
+  cdfDefSPorFC(streamptr, gridID, axisname, GRID_SPECTRAL);
+}
+
 
 static
 void cdfDefFC(stream_t *streamptr, int gridID)
 {
   char axisname[5] = "nfcX";
-  int index, iz = 0;
-  int dimID = UNDEFID;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  int ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqSize(gridID)/2;
-
-  for ( index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->ydimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_FOURIER )
-            {
-              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
-              if ( dimlen == dimlen0 )
-                {
-                  dimID = streamptr->ydimID[index];
-                  break;
-                }
-              else
-                iz++;
-            }
-        }
-    }
-
-  if ( dimID == UNDEFID )
-    {
-      if ( iz == 0 ) axisname[3] = '\0';
-      else           sprintf(&axisname[3], "%1d", iz+1);
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  streamptr->ydimID[gridindex] = dimID;
-}
-
-struct cdfDefTrajLatLonInqs {
-  int (*gridInqDimSize)(int gridID);
-  void (*gridInqDimName)(int gridID, char *dimname);
-  void (*gridInqDimStdname)(int gridID, char *dimstdname);
-  void (*gridInqDimLongname)(int gridID, char *dimlongname);
-  void (*gridInqDimUnits)(int gridID, char *dimunits);
+  cdfDefSPorFC(streamptr, gridID, axisname, GRID_FOURIER);
+}
+
+static const struct cdfDefGridAxisInqs {
+  int (*axisSize)(int gridID);
+  void (*axisName)(int gridID, char *dimname);
+  const char *(*axisNamePtr)(int gridID);
+  void (*axisStdname)(int gridID, char *dimstdname);
+  void (*axisLongname)(int gridID, char *dimlongname);
+  void (*axisUnits)(int gridID, char *dimunits);
+  double (*axisVal)(int gridID, int index);
+  const double *(*axisValsPtr)(int gridID);
+  const double *(*axisBoundsPtr)(int gridID);
+} gridInqsX = {
+  .axisSize = gridInqXsize,
+  .axisName = gridInqXname,
+  .axisNamePtr = gridInqXnamePtr,
+  .axisStdname = gridInqXstdname,
+  .axisLongname = gridInqXlongname,
+  .axisUnits = gridInqXunits,
+  .axisVal = gridInqXval,
+  .axisValsPtr = gridInqXvalsPtr,
+  .axisBoundsPtr = gridInqXboundsPtr,
+}, gridInqsY = {
+  .axisSize = gridInqYsize,
+  .axisName = gridInqYname,
+  .axisNamePtr = gridInqYnamePtr,
+  .axisStdname = gridInqYstdname,
+  .axisLongname = gridInqYlongname,
+  .axisUnits = gridInqYunits,
+  .axisVal = gridInqYval,
+  .axisValsPtr = gridInqYvalsPtr,
+  .axisBoundsPtr = gridInqYboundsPtr,
+}, gridInqsZ = {
+  .axisStdname = zaxisInqStdname,
+  .axisLongname = zaxisInqLongname,
+  .axisUnits = zaxisInqUnits,
 };
 
+static void
+cdfPutGridStdAtts(int fileID, int ncvarid,
+                  int gridID, const struct cdfDefGridAxisInqs *inqs)
+{
+  size_t len;
+  {
+    char stdname[CDI_MAX_NAME];
+    inqs->axisStdname(gridID, stdname);
+    if ( (len = strlen(stdname)) )
+      cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
+  }
+  {
+    char longname[CDI_MAX_NAME];
+    inqs->axisLongname(gridID, longname);
+    if ( (len = strlen(longname)) )
+      cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
+  }
+  {
+    char units[CDI_MAX_NAME];
+    inqs->axisUnits(gridID, units);
+    if ( (len = strlen(units)) )
+      cdf_put_att_text(fileID, ncvarid, "units", len, units);
+  }
+}
 
 static void
 cdfDefTrajLatLon(stream_t *streamptr, int gridID,
-                 const struct cdfDefTrajLatLonInqs *inqs,
+                 const struct cdfDefGridAxisInqs *inqs,
                  int *dimID, const char *sizeName)
 {
   nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
 
   int vlistID = streamptr->vlistID;
-  int dimlen = inqs->gridInqDimSize(gridID);
+  int dimlen = inqs->axisSize(gridID);
   if ( dimlen != 1 )
     Error("%s isn't 1 for %s grid!", sizeName, gridNamePtr(gridInqType(gridID)));
 
@@ -38805,34 +38949,13 @@ cdfDefTrajLatLon(stream_t *streamptr, int gridID,
 
   if ( ncvarid == UNDEFID )
     {
-      size_t len;
       int dimNcID = streamptr->basetime.ncvarid;
       int fileID  = streamptr->fileID;
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      {
-        char axisname[CDI_MAX_NAME];
-        inqs->gridInqDimName(gridID, axisname);
-        cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
-      }
-      {
-        char stdname[CDI_MAX_NAME];
-        inqs->gridInqDimStdname(gridID, stdname);
-        if ( (len = strlen(stdname)) )
-          cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-      }
-      {
-        char longname[CDI_MAX_NAME];
-        inqs->gridInqDimLongname(gridID, longname);
-        if ( (len = strlen(longname)) )
-          cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-      }
-      {
-        char units[CDI_MAX_NAME];
-        inqs->gridInqDimUnits(gridID, units);
-        if ( (len = strlen(units)) )
-          cdf_put_att_text(fileID, ncvarid, "units", len, units);
-      }
+      const char *axisname = inqs->axisNamePtr(gridID);
+      cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
+      cdfPutGridStdAtts(fileID, ncvarid, gridID, inqs);
       cdf_enddef(fileID);
       streamptr->ncmode = 2;
     }
@@ -38843,271 +38966,171 @@ cdfDefTrajLatLon(stream_t *streamptr, int gridID,
 static
 void cdfDefTrajLon(stream_t *streamptr, int gridID)
 {
-  static const struct cdfDefTrajLatLonInqs inqs =
-    { .gridInqDimSize = gridInqXsize,
-      .gridInqDimName = gridInqXname,
-      .gridInqDimStdname = gridInqXstdname,
-      .gridInqDimLongname = gridInqXlongname,
-      .gridInqDimUnits = gridInqXunits
-    };
-  cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->xdimID, "Xsize");
+  cdfDefTrajLatLon(streamptr, gridID, &gridInqsX, streamptr->xdimID, "Xsize");
 }
 
 
 static
 void cdfDefTrajLat(stream_t *streamptr, int gridID)
 {
-  static const struct cdfDefTrajLatLonInqs inqs =
-    { .gridInqDimSize = gridInqYsize,
-      .gridInqDimName = gridInqYname,
-      .gridInqDimStdname = gridInqYstdname,
-      .gridInqDimLongname = gridInqYlongname,
-      gridInqYunits
-  };
-  cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->ydimID, "Ysize");
+  cdfDefTrajLatLon(streamptr, gridID, &gridInqsY, streamptr->ydimID, "Ysize");
 }
 
+static
+int checkDimName(int fileID, size_t dimlen, char *dimname)
+{
+  /* check whether the dimenion name is already defined with the same length */
+  unsigned iz = 0;
+  int dimid = UNDEFID;
+  char name[CDI_MAX_NAME];
+
+  size_t len = strlen(dimname);
+  memcpy(name, dimname, len + 1);
+
+  do
+    {
+      if ( iz ) sprintf(name + len, "_%u", iz+1);
+
+      int dimid0, status = nc_inq_dimid(fileID, name, &dimid0);
+      if ( status != NC_NOERR )
+        break;
+      size_t dimlen0;
+      cdf_inq_dimlen(fileID, dimid0, &dimlen0);
+      if ( dimlen0 == dimlen )
+        {
+          dimid = dimid0;
+          break;
+        }
+      iz++;
+    }
+  while ( iz <= 99 );
+
+
+  if ( iz ) sprintf(dimname + len, "_%u", iz+1);
+
+  return dimid;
+}
 
 static
-int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode)
+void checkGridName(char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode)
 {
-  int index;
-  int gridID0;
   int ncdimid;
-  char axisname0[CDI_MAX_NAME];
   char axisname2[CDI_MAX_NAME];
-  int status;
 
   /* check that the name is not already defined */
-  int checkname = TRUE;
   unsigned iz = 0;
 
+  size_t axisnameLen = strlen(axisname);
+  memcpy(axisname2, axisname, axisnameLen + 1);
   do
     {
-      strcpy(axisname2, axisname);
-      if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%u", iz+1);
+      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
 
-      //status = nc_inq_varid(fileID, axisname2, &ncvarid);
-      if ( type == 'V' ) /* type Var oder Dim */
-        status = nc_inq_varid(fileID, axisname2, &ncdimid);
-      else
-        status = nc_inq_dimid(fileID, axisname2, &ncdimid);
+      int status = nc_inq_varid(fileID, axisname2, &ncdimid);
 
       if ( status != NC_NOERR )
         {
           if ( iz )
             {
               /* check that the name does not exist for other grids */
-              for ( index = 0; index < ngrids; index++ )
+              for ( int index = 0; index < ngrids; index++ )
                 {
-                  gridID0 = vlistGrid(vlistID, index);
+                  int gridID0 = vlistGrid(vlistID, index);
                   if ( gridID != gridID0 )
                     {
-                      if ( mode == 'X' ) /* mode X or Y */
-                        gridInqXname(gridID0, axisname0);
-                      else
-                        gridInqYname(gridID0, axisname0);
-
-                      if ( strcmp(axisname0, axisname2) == 0 ) break;
+                       /* mode X or Y */
+                      const char *(*query)(int)
+                        = mode == 'X' ? gridInqXnamePtr : gridInqYnamePtr;
+                      const char *axisname0 = query(gridID0);
+                      if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix;
                     }
                 }
-              if ( index == ngrids ) checkname = FALSE;
-            }
-          else
-            {
-              checkname = FALSE;
             }
+          break;
         }
-
-      if ( checkname ) iz++;
+      nextSuffix:
+      ++iz;
     }
-  while (checkname && iz <= 99);
-
+  while ( iz <= 99 );
 
-  if ( iz ) sprintf(&axisname[strlen(axisname)], "_%u", iz+1);
 
-  return (int)iz;
+  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
 }
 
 static
-void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
+int checkZaxisName(char *axisname, int fileID, int vlistID, int zaxisID, int nzaxis)
 {
-  char units[CDI_MAX_NAME];
-  char longname[CDI_MAX_NAME];
-  char stdname[CDI_MAX_NAME];
-  char axisname[CDI_MAX_NAME];
-  int index;
-  /*  int index2; */
-  int dimID = UNDEFID;
-  int dimIDs[2];
-  int ngrids = 0;
-  size_t len;
-  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvdimID = UNDEFID;
-  nc_type xtype = NC_DOUBLE;
-
-  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  if ( ndims ) ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqXsize(gridID);
-  int gridindex = vlistGridIndex(vlistID, gridID);
-
-  gridInqXname(gridID, axisname);
-  if ( axisname[0] == 0 ) Error("axis name undefined!");
-
-  gridInqXlongname(gridID, longname);
-  gridInqXstdname(gridID, stdname);
-  gridInqXunits(gridID, units);
+  char axisname2[CDI_MAX_NAME];
 
-  for ( index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->xdimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_GAUSSIAN    ||
-               gridtype0 == GRID_LONLAT      ||
-               gridtype0 == GRID_CURVILINEAR ||
-               gridtype0 == GRID_GENERIC )
-            {
-              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
-              if ( dimlen == dimlen0 )
-                if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
-                  {
-                    dimID = streamptr->xdimID[index];
-                    break;
-                  }
-              /*
-              for ( index2 = 0; index2 < index; index2++ )
-                if ( streamptr->xdimID[index] == streamptr->xdimID[index2] )
-                  break;
-              if ( index2 == index ) iz++;
-              */
-            }
-        }
-    }
+  /* check that the name is not already defined */
+  unsigned iz = 0;
 
-  if ( dimID == UNDEFID )
+  size_t axisnameLen = strlen(axisname);
+  memcpy(axisname2, axisname, axisnameLen + 1);
+  do
     {
-      int status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'X');
-      if ( status == 0 && ndims )
-        status = checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
+      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
 
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      int ncdimid, status = nc_inq_varid(fileID, axisname2, &ncdimid);
 
-      int gen_bounds = FALSE;
-      int grid_is_cyclic = gridIsCircular(gridID);
-      const double *pvals = gridInqXvalsPtr(gridID);
-      double *pbounds = NULL;
-      if ( pvals )
+      if ( status != NC_NOERR )
         {
-          cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
-
-          if ( (len = strlen(stdname)) )
-            cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-          if ( (len = strlen(longname)) )
-            cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-          if ( (len = strlen(units)) )
-            cdf_put_att_text(fileID, ncvarid, "units", len, units);
-
-          cdf_put_att_text(fileID, ncvarid, "axis", 1, "X");
-
-          if ( gridInqXboundsPtr(gridID) )
-            pbounds = (double*) gridInqXboundsPtr(gridID);
-
-          if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
+          if ( iz )
             {
-              gen_bounds = TRUE;
-              pbounds = (double*) malloc(2*dimlen*sizeof(double));
-              for ( size_t i = 0; i < dimlen-1; ++i )
+              /* check that the name does not exist for other zaxes */
+              for ( int index = 0; index < nzaxis; index++ )
                 {
-                  pbounds[i*2+1]   = (pvals[i] + pvals[i+1])/2;
-                  pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
+                  int zaxisID0 = vlistZaxis(vlistID, index);
+                  if ( zaxisID != zaxisID0 )
+                    {
+                      const char *axisname0 = zaxisInqNamePtr(zaxisID0);
+                      if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix;
+                    }
                 }
-              pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)/2;
-              pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)/2;
-            }
-          if ( pbounds )
-            {
-              size_t nvertex = 2;
-              if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-                cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
             }
-          if ( pbounds && nvdimID != UNDEFID )
-            {
-              strcat(axisname, "_");
-              strcat(axisname, BNDS_NAME);
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
-              cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
-            }
-          /*
-          if ( gridIsRotated(gridID) )
-            {
-              double north_pole = gridInqXpole(gridID);
-              cdf_put_att_double(fileID, ncvarid, "north_pole", NC_DOUBLE, 1, &north_pole);
-            }
-          */
+          break;
         }
+      nextSuffix:
+      ++iz;
+    }
+  while (iz <= 99);
 
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-
-      if ( ncvarid  != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
-      if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
-      if ( gen_bounds ) Free(pbounds);
 
-      if ( ndims == 0 ) streamptr->ncxvarID[gridindex] = ncvarid;
-    }
+  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
 
-  streamptr->xdimID[gridindex] = dimID;
+  return (int)iz;
 }
 
-static
-void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
+static void
+cdfDefAxisCommon(stream_t *streamptr, int gridID, int ndims,
+                 const struct cdfDefGridAxisInqs *gridAxisInq,
+                 int *axisDimIDs, int dimKey, char axisLetter,
+                 void (*finishCyclicBounds)(double *pbounds, size_t dimlen,
+                                            const double *pvals),
+                 int *ncAxisVarIDs)
 {
-  char units[CDI_MAX_NAME];
-  char longname[CDI_MAX_NAME];
-  char stdname[CDI_MAX_NAME];
-  char axisname[CDI_MAX_NAME];
-  int index;
-  /*  int index2; */
   int dimID = UNDEFID;
-  int dimIDs[2];
   int ngrids = 0;
-  size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
   int nvdimID = UNDEFID;
-  nc_type xtype = NC_DOUBLE;
-
-  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
+  nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
 
   int vlistID = streamptr->vlistID;
   int fileID  = streamptr->fileID;
 
   if ( ndims ) ngrids = vlistNgrids(vlistID);
 
-  size_t dimlen = (size_t)gridInqYsize(gridID);
+  size_t dimlen = (size_t)gridAxisInq->axisSize(gridID);
   int gridindex = vlistGridIndex(vlistID, gridID);
 
-  gridInqYname(gridID, axisname);
-  if ( axisname[0] == 0 ) Error("axis name undefined!");
+  const char *axisname = gridAxisInq->axisNamePtr(gridID);
+  size_t axisnameLen = strlen(axisname);
 
-  gridInqYlongname(gridID, longname);
-  gridInqYstdname(gridID, stdname);
-  gridInqYunits(gridID, units);
+  if ( axisname[0] == 0 ) Error("axis name undefined!");
 
-  for ( index = 0; index < ngrids; index++ )
+  for ( int index = 0; index < ngrids; index++ )
     {
-      if ( streamptr->ydimID[index] != UNDEFID )
+      if ( axisDimIDs[index] != UNDEFID )
         {
           int gridID0 = vlistGrid(vlistID, index);
           int gridtype0 = gridInqType(gridID0);
@@ -39116,89 +39139,91 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              size_t dimlen0 = (size_t)gridInqYsize(gridID0);
+              size_t dimlen0 = (size_t)gridAxisInq->axisSize(gridID0);
               if ( dimlen == dimlen0 )
-                if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
+                {
+                  double (*inqVal)(int gridID, int index)
+                    = gridAxisInq->axisVal;
+                  if ( IS_EQUAL(inqVal(gridID0, 0), inqVal(gridID, 0)) &&
+                       IS_EQUAL(inqVal(gridID0, (int)dimlen-1), inqVal(gridID, (int)dimlen-1)) )
                   {
-                    dimID = streamptr->ydimID[index];
+                    dimID = axisDimIDs[index];
                     break;
                   }
-              /*
-              for ( index2 = 0; index2 < index; index2++ )
-                if ( streamptr->ydimID[index] == streamptr->ydimID[index2] )
-                  break;
-              if ( index2 == index ) iz++;
-              */
+                }
             }
         }
     }
 
   if ( dimID == UNDEFID )
     {
-      int status;
-      status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'Y');
-      if ( status == 0 && ndims )
-        status = checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'Y');
+      const double *pvals = gridAxisInq->axisValsPtr(gridID);
+
+      /* enough to append _ plus up to 100 decimal and trailing \0 */
+      char extendedAxisname[axisnameLen + 4 + 1];
+      memcpy(extendedAxisname, axisname, axisnameLen + 1);
+      checkGridName(extendedAxisname, fileID, vlistID, gridID, ngrids, axisLetter);
+      size_t extendedAxisnameLen
+        = axisnameLen + strlen(extendedAxisname + axisnameLen);
 
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      if ( ndims )
+        {
+          char dimname[CDI_MAX_NAME+3];
+          dimname[0] = 0;
 
-      int gen_bounds = FALSE;
+          if ( pvals == NULL )
+            cdiGridInqString(gridID, dimKey, CDI_MAX_NAME, dimname);
+
+          if ( dimname[0] == 0 ) strcpy(dimname, extendedAxisname);
+          dimID = checkDimName(fileID, dimlen, dimname);
+
+          if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
+        }
+
+      bool gen_bounds = false;
       int grid_is_cyclic = gridIsCircular(gridID);
-      const double *pvals = gridInqYvalsPtr(gridID);
       double *pbounds = NULL;
       if ( pvals )
         {
-          cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
-
-          if ( (len = strlen(stdname)) )
-            cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-          if ( (len = strlen(longname)) )
-            cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-          if ( (len = strlen(units)) )
-            cdf_put_att_text(fileID, ncvarid, "units", len, units);
+          cdf_def_var(fileID, extendedAxisname, xtype, ndims, &dimID, &ncvarid);
 
-          cdf_put_att_text(fileID, ncvarid, "axis", 1, "Y");
+          cdfPutGridStdAtts(fileID, ncvarid, gridID, gridAxisInq);
+          {
+            char axisStr[2] = { axisLetter, '\0' };
+            cdf_put_att_text(fileID, ncvarid, "axis", 1, axisStr);
+          }
 
-          if ( gridInqYboundsPtr(gridID) )
-            pbounds = (double*) gridInqYboundsPtr(gridID);
+          pbounds = (double *)gridAxisInq->axisBoundsPtr(gridID);
 
           if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
             {
-              gen_bounds = TRUE;
-              pbounds = (double*) malloc(2*dimlen*sizeof(double));
+              gen_bounds = true;
+              pbounds = (double*) Malloc(2*dimlen*sizeof(double));
               for ( size_t i = 0; i < dimlen-1; ++i )
                 {
                   pbounds[i*2+1]   = (pvals[i] + pvals[i+1])/2;
                   pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
                 }
-              pbounds[0] = (pvals[0] < 0) ? -90 : 90;
-              pbounds[2*dimlen-1] = (pvals[dimlen-1] < 0) ? -90 : 90;
+              finishCyclicBounds(pbounds, dimlen, pvals);
             }
           if ( pbounds )
             {
               size_t nvertex = 2;
-              if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-                cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+              if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+                cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
             }
           if ( pbounds && nvdimID != UNDEFID )
             {
-              strcat(axisname, "_");
-              strcat(axisname, BNDS_NAME);
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
-              cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
+              char boundsname[extendedAxisnameLen + 1 + sizeof (bndsName)];
+              memcpy(boundsname, axisname, extendedAxisnameLen);
+              boundsname[extendedAxisnameLen] = '_';
+              memcpy(boundsname + extendedAxisnameLen + 1, bndsName, sizeof bndsName);
+              int dimIDs[2] = { dimID, nvdimID };
+              cdf_def_var(fileID, boundsname, xtype, 2, dimIDs, &ncbvarid);
+              cdf_put_att_text(fileID, ncvarid, "bounds", extendedAxisnameLen + sizeof (bndsName), boundsname);
             }
-          /*
-          if ( gridIsRotated(gridID) )
-            {
-              double north_pole = gridInqYpole(gridID);
-              cdf_put_att_double(fileID, ncvarid, "north_pole", NC_DOUBLE, 1, &north_pole);
-            }
-          */
         }
 
       cdf_enddef(fileID);
@@ -39208,10 +39233,40 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
       if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
       if ( gen_bounds ) Free(pbounds);
 
-      if ( ndims == 0 ) streamptr->ncyvarID[gridindex] = ncvarid;
+      if ( ndims == 0 ) ncAxisVarIDs[gridindex] = ncvarid;
     }
 
-  streamptr->ydimID[gridindex] = dimID;
+  axisDimIDs[gridindex] = dimID;
+}
+
+static void
+finishCyclicXBounds(double *pbounds, size_t dimlen, const double *pvals)
+{
+  pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)*0.5;
+  pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)*0.5;
+}
+
+static
+void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
+{
+  cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsX, streamptr->xdimID,
+                   CDI_GRID_XDIMNAME, 'X', finishCyclicXBounds,
+                   streamptr->ncxvarID);
+}
+
+static void
+finishCyclicYBounds(double *pbounds, size_t dimlen, const double *pvals)
+{
+  pbounds[0] = copysign(90.0, pvals[0]);
+  pbounds[2*dimlen-1] = copysign(90.0, pvals[dimlen-1]);
+}
+
+static
+void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
+{
+  cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsY, streamptr->ydimID,
+                   CDI_GRID_YDIMNAME, 'Y', finishCyclicYBounds,
+                   streamptr->ncyvarID);
 }
 
 static
@@ -39226,76 +39281,43 @@ void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int co
 #endif
 }
 
-
 static
 void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 {
-  char xunits[CDI_MAX_NAME];
-  char xlongname[CDI_MAX_NAME];
-  char xstdname[CDI_MAX_NAME];
-  char yunits[CDI_MAX_NAME];
-  char ylongname[CDI_MAX_NAME];
-  char ystdname[CDI_MAX_NAME];
-  char xaxisname[CDI_MAX_NAME];
-  char yaxisname[CDI_MAX_NAME];
-  char xdimname[4] = "x";
-  char ydimname[4] = "y";
-  int index;
   int xdimID = UNDEFID;
   int ydimID = UNDEFID;
-  int dimIDs[3];
-  size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  int nvdimID = UNDEFID;
-  nc_type xtype = NC_DOUBLE;
-
-  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
+  nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
 
   int vlistID = streamptr->vlistID;
   int fileID  = streamptr->fileID;
 
   int ngrids = vlistNgrids(vlistID);
 
+  size_t dimlen = (size_t)gridInqSize(gridID);
   size_t xdimlen = (size_t)gridInqXsize(gridID);
   size_t ydimlen = (size_t)gridInqYsize(gridID);
   int gridindex = vlistGridIndex(vlistID, gridID);
 
-  gridInqXname(gridID, xaxisname);
-  gridInqXlongname(gridID, xlongname);
-  gridInqXstdname(gridID, xstdname);
-  gridInqXunits(gridID, xunits);
-  gridInqYname(gridID, yaxisname);
-  gridInqYlongname(gridID, ylongname);
-  gridInqYstdname(gridID, ystdname);
-  gridInqYunits(gridID, yunits);
-
-  for ( index = 0; index < ngrids; index++ )
+  for ( int index = 0; index < ngrids; index++ )
     {
       if ( streamptr->xdimID[index] != UNDEFID )
         {
           int gridID0 = vlistGrid(vlistID, index);
           int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_GAUSSIAN    ||
-               gridtype0 == GRID_LONLAT      ||
-               gridtype0 == GRID_CURVILINEAR ||
-               gridtype0 == GRID_GENERIC )
+          if ( gridtype0 == GRID_CURVILINEAR )
             {
-              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
-              if ( xdimlen == dimlen0 )
+              size_t dimlen0 = (size_t)gridInqSize(gridID0);
+              if ( dimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)xdimlen-1), gridInqXval(gridID, (int)xdimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
+                     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
                   {
                     xdimID = streamptr->xdimID[index];
-                    ncxvarid = streamptr->ncxvarID[index];
-                    break;
-                  }
-              dimlen0 = (size_t)gridInqYsize(gridID0);
-              if ( ydimlen == dimlen0 )
-                if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, (int)xdimlen-1), gridInqYval(gridID, (int)xdimlen-1)) )
-                  {
                     ydimID = streamptr->ydimID[index];
+                    ncxvarid = streamptr->ncxvarID[index];
                     ncyvarid = streamptr->ncyvarID[index];
                     break;
                   }
@@ -39305,81 +39327,90 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 
   if ( xdimID == UNDEFID || ydimID == UNDEFID )
     {
-      checkGridName('V', xaxisname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('V', yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
-      checkGridName('D', xdimname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('D', ydimname, fileID, vlistID, gridID, ngrids, 'Y');
-
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+      {
+        char xdimname[CDI_MAX_NAME+3];
+        xdimname[0] = 0;
+        cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname);
+        if ( xdimname[0] == 0 ) { xdimname[0] = 'x'; xdimname[1] = 0; }
+        xdimID = checkDimName(fileID, xdimlen, xdimname);
+        if ( xdimID == UNDEFID ) cdf_def_dim(fileID, xdimname, xdimlen, &xdimID);
+      }
+      {
+        char ydimname[CDI_MAX_NAME+3];
+        ydimname[0] = 0;
+        cdiGridInqString(gridID, CDI_GRID_YDIMNAME, CDI_MAX_NAME, ydimname);
+        if ( ydimname[0] == 0 ) { ydimname[0] = 'y'; ydimname[1] = 0; }
+        ydimID = checkDimName(fileID, ydimlen, ydimname);
+        if ( ydimID == UNDEFID ) cdf_def_dim(fileID, ydimname, ydimlen, &ydimID);
+      }
 
-      cdf_def_dim(fileID, xdimname, xdimlen, &xdimID);
-      cdf_def_dim(fileID, ydimname, ydimlen, &ydimID);
-
+      int nvdimID = UNDEFID;
+      int dimIDs[3];
       if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
         {
+          char vdimname[CDI_MAX_NAME+3];
+          vdimname[0] = 0;
+          cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname);
+          if ( vdimname[0] == 0 ) strcpy(vdimname, "nv4");
           size_t nvertex = 4;
-          if ( nc_inq_dimid(fileID, "nv4", &nvdimID) != NC_NOERR )
-            cdf_def_dim(fileID, "nv4", nvertex, &nvdimID);
+          nvdimID = checkDimName(fileID, nvertex, vdimname);
+          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
         }
 
       dimIDs[0] = ydimID;
       dimIDs[1] = xdimID;
+      dimIDs[2] = nvdimID;
 
       if ( gridInqXvalsPtr(gridID) )
         {
+          char xaxisname[CDI_MAX_NAME];
+          gridInqXname(gridID, xaxisname);
+          checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X');
+
           cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid);
           cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(xstdname)) )
-            cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
-          if ( (len = strlen(xlongname)) )
-            cdf_put_att_text(fileID, ncxvarid, "long_name", len, xlongname);
-          if ( (len = strlen(xunits)) )
-            cdf_put_att_text(fileID, ncxvarid, "units", len, xunits);
+          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
 
           /* attribute for Panoply */
           cdf_put_att_text(fileID, ncxvarid, "_CoordinateAxisType", 3, "Lon");
 
           if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              strcat(xaxisname, "_");
-              strcat(xaxisname, BNDS_NAME);
-              dimIDs[0] = ydimID;
-              dimIDs[1] = xdimID;
-              dimIDs[2] = nvdimID;
+              size_t xaxisnameLen = strlen(xaxisname);
+              xaxisname[xaxisnameLen] = '_';
+              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid);
               cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
+              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
             }
         }
 
       if ( gridInqYvalsPtr(gridID) )
         {
+          char yaxisname[CDI_MAX_NAME];
+          gridInqYname(gridID, yaxisname);
+          checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
+
           cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid);
           cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(ystdname)) )
-            cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
-          if ( (len = strlen(ylongname)) )
-            cdf_put_att_text(fileID, ncyvarid, "long_name", len, ylongname);
-          if ( (len = strlen(yunits)) )
-            cdf_put_att_text(fileID, ncyvarid, "units", len, yunits);
+          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
 
           /* attribute for Panoply */
           cdf_put_att_text(fileID, ncyvarid, "_CoordinateAxisType", 3, "Lat");
 
           if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              strcat(yaxisname, "_");
-              strcat(yaxisname, BNDS_NAME);
-              dimIDs[0] = ydimID;
-              dimIDs[1] = xdimID;
-              dimIDs[2] = nvdimID;
+              size_t yaxisnameLen = strlen(yaxisname);
+              yaxisname[yaxisnameLen] = '_';
+              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid);
               cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
+              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
             }
         }
 
@@ -39417,19 +39448,15 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 static
 void cdfDefRgrid(stream_t *streamptr, int gridID)
 {
-  char axisname[7] = "rgridX";
-  int index, iz = 0;
   int dimID = UNDEFID;
-  int lwarn = TRUE;
 
   int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
   int ngrids = vlistNgrids(vlistID);
 
   size_t dimlen = (size_t)gridInqSize(gridID);
 
-  for ( index = 0; index < ngrids; index++ )
+  int iz = 0;
+  for ( int index = 0; index < ngrids; index++ )
     {
       if ( streamptr->xdimID[index] != UNDEFID )
         {
@@ -39444,21 +39471,23 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
                   dimID = streamptr->xdimID[index];
                   break;
                 }
-              else
-                iz++;
+              iz++;
             }
         }
     }
 
   if ( dimID == UNDEFID )
     {
+      int fileID  = streamptr->fileID;
+      static bool lwarn = true;
       if ( lwarn )
         {
           Warning("Creating a NetCDF file with data on a gaussian reduced grid.");
           Warning("The further processing of the resulting file is unsupported!");
-          lwarn = FALSE;
+          lwarn = false;
         }
 
+      char axisname[7] = "rgridX";
       if ( iz == 0 ) axisname[5] = '\0';
       else           sprintf(&axisname[5], "%1d", iz+1);
 
@@ -39477,18 +39506,16 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
 static
 void cdfDefGdim(stream_t *streamptr, int gridID)
 {
-  int index, iz = 0;
+  int iz = 0;
   int dimID = UNDEFID;
 
   int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
   int ngrids = vlistNgrids(vlistID);
 
   size_t dimlen = (size_t)gridInqSize(gridID);
 
   if ( gridInqYsize(gridID) == 0 )
-    for ( index = 0; index < ngrids; index++ )
+    for ( int index = 0; index < ngrids; index++ )
       {
         if ( streamptr->xdimID[index] != UNDEFID )
           {
@@ -39509,7 +39536,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
       }
 
   if ( gridInqXsize(gridID) == 0 )
-    for ( index = 0; index < ngrids; index++ )
+    for ( int index = 0; index < ngrids; index++ )
       {
         if ( streamptr->ydimID[index] != UNDEFID )
           {
@@ -39531,18 +39558,15 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
-      char axisname[CDI_MAX_NAME];
-      strcpy(axisname, "gsize");
+      int fileID  = streamptr->fileID;
+      char dimname[CDI_MAX_NAME];
+      strcpy(dimname, "gsize");
+
+      dimID = checkDimName(fileID, dimlen, dimname);
 
-      checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
-      /*
-      if ( iz == 0 ) axisname[5] = '\0';
-      else           sprintf(&axisname[5], "%1d", iz+1);
-      */
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      //printf("axisname, dimlen %s %d\n", axisname, dimlen);
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
 
       cdf_enddef(fileID);
       streamptr->ncmode = 2;
@@ -39563,14 +39587,9 @@ void cdfDefGridReference(stream_t *streamptr, int gridID)
       cdf_put_att_int(fileID, NC_GLOBAL, "number_of_grid_used", NC_INT, 1, &number);
     }
 
-  if ( gridInqReference(gridID, NULL) )
-    {
-      char gridfile[8912];
-      gridInqReference(gridID, gridfile);
-
-      if ( gridfile[0] != 0 )
-        cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile);
-    }
+  const char *gridfile = gridInqReferencePtr(gridID);
+  if ( gridfile && gridfile[0] != 0 )
+    cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile);
 }
 
 static
@@ -39616,17 +39635,7 @@ void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID)
 static
 void cdfDefUnstructured(stream_t *streamptr, int gridID)
 {
-  char xunits[CDI_MAX_NAME];
-  char xlongname[CDI_MAX_NAME];
-  char xstdname[CDI_MAX_NAME];
-  char yunits[CDI_MAX_NAME];
-  char ylongname[CDI_MAX_NAME];
-  char ystdname[CDI_MAX_NAME];
-  char xaxisname[CDI_MAX_NAME];
-  char yaxisname[CDI_MAX_NAME];
-  int index;
   int dimID = UNDEFID;
-  size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
   int nvdimID = UNDEFID;
@@ -39642,16 +39651,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
   size_t dimlen = (size_t)gridInqSize(gridID);
   int gridindex = vlistGridIndex(vlistID, gridID);
 
-  gridInqXname(gridID, xaxisname);
-  gridInqXlongname(gridID, xlongname);
-  gridInqXstdname(gridID, xstdname);
-  gridInqXunits(gridID, xunits);
-  gridInqYname(gridID, yaxisname);
-  gridInqYlongname(gridID, ylongname);
-  gridInqYstdname(gridID, ystdname);
-  gridInqYunits(gridID, yunits);
-
-  for ( index = 0; index < ngrids; index++ )
+  for ( int index = 0; index < ngrids; index++ )
     {
       if ( streamptr->xdimID[index] != UNDEFID )
         {
@@ -39663,7 +39663,9 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
               if ( dimlen == dimlen0 )
 		if ( gridInqNvertex(gridID0) == gridInqNvertex(gridID) &&
 		     IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
+		     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
 		  {
 		    dimID = streamptr->xdimID[index];
                     ncxvarid = streamptr->ncxvarID[index];
@@ -39677,22 +39679,26 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
-      char axisname[CDI_MAX_NAME];
-      char vertname[CDI_MAX_NAME];
-      strcpy(axisname, "ncells");
-      strcpy(vertname, "vertices");
-
-      checkGridName('V', xaxisname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('V', yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
-      checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('D', vertname, fileID, vlistID, gridID, ngrids, 'X');
-
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      {
+        char xdimname[CDI_MAX_NAME+3];
+        xdimname[0] = 0;
+        cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname);
+        if ( xdimname[0] == 0 ) strcpy(xdimname, "ncells");
+        dimID = checkDimName(fileID, dimlen, xdimname);
+        if ( dimID == UNDEFID ) cdf_def_dim(fileID, xdimname, dimlen, &dimID);
+      }
 
       size_t nvertex = (size_t)gridInqNvertex(gridID);
-      if ( nvertex > 0 ) cdf_def_dim(fileID, vertname, nvertex, &nvdimID);
+      if ( nvertex > 0 )
+        {
+          char vdimname[CDI_MAX_NAME+3];
+          vdimname[0] = 0;
+          cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname);
+          if ( vdimname[0] == 0 ) strcpy(vdimname, "vertices");
+          nvdimID = checkDimName(fileID, nvertex, vdimname);
+          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
+        }
 
       cdfDefGridReference(streamptr, gridID);
 
@@ -39700,53 +39706,47 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
       if ( gridInqXvalsPtr(gridID) )
         {
+          char xaxisname[CDI_MAX_NAME];
+          gridInqXname(gridID, xaxisname);
+          checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X');
           cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid);
           cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(xstdname)) )
-            cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
-          if ( (len = strlen(xlongname)) )
-            cdf_put_att_text(fileID, ncxvarid, "long_name", len, xlongname);
-          if ( (len = strlen(xunits)) )
-            cdf_put_att_text(fileID, ncxvarid, "units", len, xunits);
+          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
 
           if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              int dimIDs[2];
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              strcat(xaxisname, "_");
-              strcat(xaxisname, BNDS_NAME);
+              int dimIDs[2] = { dimID, nvdimID };
+              size_t xaxisnameLen = strlen(xaxisname);
+              xaxisname[xaxisnameLen] = '_';
+              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid);
               cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
+              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
             }
         }
 
       if ( gridInqYvalsPtr(gridID) )
         {
+          char yaxisname[CDI_MAX_NAME];
+          gridInqYname(gridID, yaxisname);
+          checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
           cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid);
           cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(ystdname)) )
-            cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
-          if ( (len = strlen(ylongname)) )
-            cdf_put_att_text(fileID, ncyvarid, "long_name", len, ylongname);
-          if ( (len = strlen(yunits)) )
-            cdf_put_att_text(fileID, ncyvarid, "units", len, yunits);
+          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
 
           if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              int dimIDs[2];
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              strcat(yaxisname, "_");
-              strcat(yaxisname, BNDS_NAME);
+              int dimIDs[2] = { dimID, nvdimID };
+              size_t yaxisnameLen = strlen(yaxisname);
+              yaxisname[yaxisnameLen] = '_';
+              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid);
               cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
+              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
             }
         }
 
@@ -39780,6 +39780,12 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
   streamptr->ncavarID[gridindex] = ncavarid;
 }
 
+struct attTxtTab2
+{
+  const char *attName, *attVal;
+  size_t valLen;
+};
+
 static
 void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
 {
@@ -39796,7 +39802,6 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
       int ncdimid, ncdimid2;
       int hyaiid, hybiid, hyamid, hybmid;
       double mval;
-      char tmpname[CDI_MAX_NAME];
 
       if ( streamptr->vct.ilev > 0 )
         {
@@ -39822,22 +39827,34 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
       cdf_def_var(fileID, "hyam", NC_DOUBLE, 1, &ncdimid,  &hyamid);
       cdf_def_var(fileID, "hybm", NC_DOUBLE, 1, &ncdimid,  &hybmid);
 
-      strcpy(tmpname, "hybrid A coefficient at layer interfaces");
-      cdf_put_att_text(fileID, hyaiid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "Pa");
-      cdf_put_att_text(fileID, hyaiid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hybrid B coefficient at layer interfaces");
-      cdf_put_att_text(fileID, hybiid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "1");
-      cdf_put_att_text(fileID, hybiid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hybrid A coefficient at layer midpoints");
-      cdf_put_att_text(fileID, hyamid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "Pa");
-      cdf_put_att_text(fileID, hyamid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hybrid B coefficient at layer midpoints");
-      cdf_put_att_text(fileID, hybmid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "1");
-      cdf_put_att_text(fileID, hybmid, "units", strlen(tmpname), tmpname);
+      {
+        static const char lname_n[] = "long_name",
+          lname_v_ai[] = "hybrid A coefficient at layer interfaces",
+          units_n[] = "units",
+          units_v_ai[] = "Pa",
+          lname_v_bi[] = "hybrid B coefficient at layer interfaces",
+          units_v_bi[] = "1",
+          lname_v_am[] = "hybrid A coefficient at layer midpoints",
+          units_v_am[] = "Pa",
+          lname_v_bm[] = "hybrid B coefficient at layer midpoints",
+          units_v_bm[] = "1";
+        static const struct attTxtTab2 tab[]
+          = {
+          { lname_n, lname_v_ai, sizeof (lname_v_ai) - 1 },
+          { units_n, units_v_ai, sizeof (units_v_ai) - 1 },
+          { lname_n, lname_v_bi, sizeof (lname_v_bi) - 1 },
+          { units_n, units_v_bi, sizeof (units_v_bi) - 1 },
+          { lname_n, lname_v_am, sizeof (lname_v_am) - 1 },
+          { units_n, units_v_am, sizeof (units_v_am) - 1 },
+          { lname_n, lname_v_bm, sizeof (lname_v_bm) - 1 },
+          { units_n, units_v_bm, sizeof (units_v_bm) - 1 },
+        };
+        enum { tabLen = sizeof (tab) / sizeof (tab[0]) };
+        int ids[tabLen] = { hyaiid, hyaiid, hybiid, hybiid,
+                            hyamid, hyamid, hybmid, hybmid };
+        for ( size_t i = 0; i < tabLen; ++i )
+          cdf_put_att_text(fileID, ids[i], tab[i].attName, tab[i].valLen, tab[i].attVal);
+      }
 
       cdf_enddef(fileID);
       streamptr->ncmode = 2;
@@ -39870,7 +39887,6 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
 
       int mlev = ilev - 1;
       int hyaiid = 0, hybiid = 0, hyamid, hybmid;
-      char tmpname[CDI_MAX_NAME];
 
       if ( streamptr->vct.ilev > 0 )
         {
@@ -39895,28 +39911,43 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
       cdf_def_var(fileID, "ap", NC_DOUBLE, 1, dimIDs,  &hyamid);
       cdf_def_var(fileID, "b",  NC_DOUBLE, 1, dimIDs,  &hybmid);
 
-      strcpy(tmpname, "vertical coordinate formula term: ap(k)");
-      cdf_put_att_text(fileID, hyamid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "Pa");
-      cdf_put_att_text(fileID, hyamid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "vertical coordinate formula term: b(k)");
-      cdf_put_att_text(fileID, hybmid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "1");
-      cdf_put_att_text(fileID, hybmid, "units", strlen(tmpname), tmpname);
+      {
+        static const char lname[] = "vertical coordinate formula term: ap(k)";
+        cdf_put_att_text(fileID, hyamid, "long_name", sizeof (lname) - 1, lname);
+      }
+      {
+        static const char units[] = "Pa";
+        cdf_put_att_text(fileID, hyamid, "units", sizeof (units) - 1, units);
+      }
+      {
+        static const char lname[] = "vertical coordinate formula term: b(k)";
+        cdf_put_att_text(fileID, hybmid, "long_name", sizeof (lname) - 1, lname);
+      }
+      {
+        static const char units[] = "1";
+        cdf_put_att_text(fileID, hybmid, "units", sizeof (units) - 1, units);
+      }
 
       if ( ncbndsID != -1 )
         {
           cdf_def_var(fileID, "ap_bnds", NC_DOUBLE, 2, dimIDs, &hyaiid);
           cdf_def_var(fileID, "b_bnds",  NC_DOUBLE, 2, dimIDs, &hybiid);
-
-          strcpy(tmpname, "vertical coordinate formula term: ap(k+1/2)");
-          cdf_put_att_text(fileID, hyaiid, "long_name", strlen(tmpname), tmpname);
-          strcpy(tmpname, "Pa");
-          cdf_put_att_text(fileID, hyaiid, "units", strlen(tmpname), tmpname);
-          strcpy(tmpname, "vertical coordinate formula term: b(k+1/2)");
-          cdf_put_att_text(fileID, hybiid, "long_name", strlen(tmpname), tmpname);
-          strcpy(tmpname, "1");
-          cdf_put_att_text(fileID, hybiid, "units", strlen(tmpname), tmpname);
+          {
+            static const char lname[] = "vertical coordinate formula term: ap(k+1/2)";
+            cdf_put_att_text(fileID, hyaiid, "long_name", sizeof (lname) - 1, lname);
+          }
+          {
+            static const char units[] = "Pa";
+            cdf_put_att_text(fileID, hyaiid, "units", sizeof (units) - 1, units);
+          }
+          {
+            static const char lname[] = "vertical coordinate formula term: b(k+1/2)";
+            cdf_put_att_text(fileID, hybiid, "long_name", sizeof (lname) - 1, lname);
+          }
+          {
+            static const char units[] = "1";
+            cdf_put_att_text(fileID, hybiid, "units", sizeof (units) - 1, units);
+          }
         }
 
       cdf_enddef(fileID);
@@ -39952,10 +39983,11 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
     }
 }
 
+struct attTxtTab { const char *txt; size_t txtLen; };
+
 static
 void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
 {
-  char tmpname[CDI_MAX_NAME];
   int fileID  = streamptr->fileID;
 
   if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
@@ -39963,32 +39995,50 @@ void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int
   cdf_def_dim(fileID, axisname, dimlen, dimID);
   cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
 
-  strcpy(tmpname, "hybrid_sigma_pressure");
-  cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(tmpname), tmpname);
+  {
+    static const char sname[] = "hybrid_sigma_pressure";
+    cdf_put_att_text(fileID, ncvarid, "standard_name", sizeof (sname) - 1, sname);
+  }
+  {
+    static const char *attName[] = {
+      "long_name",
+      "formula",
+      "formula_terms"
+    };
+    enum { nAtt = sizeof (attName) / sizeof (attName[0]) };
+    static const char lname_m[] = "hybrid level at layer midpoints",
+      formula_m[] = "hyam hybm (mlev=hyam+hybm*aps)",
+      fterms_m[] = "ap: hyam b: hybm ps: aps",
+      lname_i[] = "hybrid level at layer interfaces",
+      formula_i[] = "hyai hybi (ilev=hyai+hybi*aps)",
+      fterms_i[] = "ap: hyai b: hybi ps: aps";
+    static const struct attTxtTab tab[2][nAtt] = {
+      {
+        { lname_i, sizeof (lname_i) - 1 },
+        { formula_i, sizeof (formula_i) - 1 },
+        { fterms_i, sizeof (fterms_i) - 1 }
+      },
+      {
+        { lname_m, sizeof (lname_m) - 1 },
+        { formula_m, sizeof (formula_m) - 1 },
+        { fterms_m, sizeof (fterms_m) - 1 }
+      }
+    };
 
-  if ( type == ZAXIS_HYBRID )
-    {
-      strcpy(tmpname, "hybrid level at layer midpoints");
-      cdf_put_att_text(fileID, ncvarid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hyam hybm (mlev=hyam+hybm*aps)");
-      cdf_put_att_text(fileID, ncvarid, "formula", strlen(tmpname), tmpname);
-      strcpy(tmpname, "ap: hyam b: hybm ps: aps");
-      cdf_put_att_text(fileID, ncvarid, "formula_terms", strlen(tmpname), tmpname);
-    }
-  else
-    {
-      strcpy(tmpname, "hybrid level at layer interfaces");
-      cdf_put_att_text(fileID, ncvarid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hyai hybi (ilev=hyai+hybi*aps)");
-      cdf_put_att_text(fileID, ncvarid, "formula", strlen(tmpname), tmpname);
-      strcpy(tmpname, "ap: hyai b: hybi ps: aps");
-      cdf_put_att_text(fileID, ncvarid, "formula_terms", strlen(tmpname), tmpname);
-    }
+    size_t tabSelect = type == ZAXIS_HYBRID;
+    for (size_t i = 0; i < nAtt; ++i)
+      cdf_put_att_text(fileID, ncvarid, attName[i],
+                       tab[tabSelect][i].txtLen, tab[tabSelect][i].txt);
+  }
 
-  strcpy(tmpname, "level");
-  cdf_put_att_text(fileID, ncvarid, "units", strlen(tmpname), tmpname);
-  strcpy(tmpname, "down");
-  cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
+  {
+    static const char units[] = "level";
+    cdf_put_att_text(fileID, ncvarid, "units", sizeof (units) - 1, units);
+  }
+  {
+    static const char direction[] = "down";
+    cdf_put_att_text(fileID, ncvarid, "positive", sizeof (direction) - 1, direction);
+  }
 
   cdf_enddef(fileID);
   streamptr->ncmode = 2;
@@ -40022,24 +40072,34 @@ void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zax
   cdf_def_dim(fileID, axisname, dimlen, dimID);
   cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
 
-  char tmpname[CDI_MAX_NAME];
-  strcpy(tmpname, "atmosphere_hybrid_sigma_pressure_coordinate");
-  cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(tmpname), tmpname);
-
-  strcpy(tmpname, "hybrid sigma pressure coordinate");
-  cdf_put_att_text(fileID, ncvarid, "long_name", strlen(tmpname), tmpname);
-  strcpy(tmpname, "p = ap + b*ps");
-  cdf_put_att_text(fileID, ncvarid, "formula", strlen(tmpname), tmpname);
-  strcpy(tmpname, "ap: ap b: b ps: ");
-  strcat(tmpname, psname);
-  cdf_put_att_text(fileID, ncvarid, "formula_terms", strlen(tmpname), tmpname);
-
-  strcpy(tmpname, "1");
-  cdf_put_att_text(fileID, ncvarid, "units", strlen(tmpname), tmpname);
-  strcpy(tmpname, "Z");
-  cdf_put_att_text(fileID, ncvarid, "axis", strlen(tmpname), tmpname);
-  strcpy(tmpname, "down");
-  cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
+  {
+    static const char sname[] = "standard_name",
+      sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
+      lname[] = "long_name",
+      lname_v[] = "hybrid sigma pressure coordinate",
+      formula[] = "formula",
+      formula_v[] = "p = ap + b*ps",
+      fterms[] = "formula_terms",
+      fterms_v[] = "ap: ap b: b ps: ",
+      units[] = "units",
+      units_v[] = "1",
+      axis[] = "axis",
+      axis_v[] = "Z",
+      direction[] = "positive",
+      direction_v[] = "down";
+    struct attTxtTab2 tab[] = {
+      { sname, sname_v, sizeof (sname_v) - 1 },
+      { lname, lname_v, sizeof (lname_v) - 1 },
+      { formula, formula_v, sizeof (formula_v) - 1 },
+      { fterms, fterms_v, sizeof (fterms_v) - 1 },
+      { units, units_v, sizeof (units_v) - 1 },
+      { axis, axis_v, sizeof (axis_v) - 1 },
+      { direction, direction_v, sizeof (direction_v) - 1 },
+    };
+    enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
+    for (size_t i = 0; i < nAtt; ++i)
+      cdf_put_att_text(fileID, ncvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
+  }
 
   int ncbvarid = UNDEFID;
   int nvdimID = UNDEFID;
@@ -40062,31 +40122,41 @@ void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zax
 
   //if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
     {
-      int dimIDs[2];
       size_t nvertex = 2;
-      if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-        cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+        cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
 
       if ( nvdimID != UNDEFID )
         {
-          strcat(axisname, "_");
-          strcat(axisname, BNDS_NAME);
-          dimIDs[0] = *dimID;
-          dimIDs[1] = nvdimID;
+          size_t axisnameLen = strlen(axisname);
+          axisname[axisnameLen] = '_';
+          memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
+          axisnameLen += sizeof (bndsName);
+          int dimIDs[2] = { *dimID, nvdimID };
           cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
-          cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
-
-          strcpy(tmpname, "atmosphere_hybrid_sigma_pressure_coordinate");
-          cdf_put_att_text(fileID, ncbvarid, "standard_name", strlen(tmpname), tmpname);
-
-          strcpy(tmpname, "p = ap + b*ps");
-          cdf_put_att_text(fileID, ncbvarid, "formula", strlen(tmpname), tmpname);
-          strcpy(tmpname, "ap: ap_bnds b: b_bnds ps: ");
-          strcat(tmpname, psname);
-          cdf_put_att_text(fileID, ncbvarid, "formula_terms", strlen(tmpname), tmpname);
-
-          strcpy(tmpname, "1");
-          cdf_put_att_text(fileID, ncbvarid, "units", strlen(tmpname), tmpname);
+          cdf_put_att_text(fileID, ncvarid, "bounds", axisnameLen, axisname);
+          {
+            static const char sname[] = "standard_name",
+              sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
+              formula[] = "formula",
+              formula_v[] = "p = ap + b*ps";
+            struct attTxtTab2 tab[] = {
+              { sname, sname_v, sizeof (sname_v) - 1 },
+              { formula, formula_v, sizeof (formula_v) - 1 },
+            };
+            enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
+            for (size_t i = 0; i < nAtt; ++i)
+              cdf_put_att_text(fileID, ncbvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
+          }
+          {
+            char txt[CDI_MAX_NAME];
+            size_t len = (size_t)(sprintf(txt, "%s%s", "ap: ap_bnds b: b_bnds ps: ", psname));
+            cdf_put_att_text(fileID, ncbvarid, "formula_terms", len, txt);
+          }
+          {
+            static const char units[] = "1";
+            cdf_put_att_text(fileID, ncbvarid, "units", sizeof (units) - 1, units);
+          }
         }
     }
 
@@ -40131,20 +40201,11 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 {
   /*  char zaxisname0[CDI_MAX_NAME]; */
   char axisname[CDI_MAX_NAME];
-  char stdname[CDI_MAX_NAME];
-  char longname[CDI_MAX_NAME];
-  char units[CDI_MAX_NAME];
-  char tmpname[CDI_MAX_NAME];
-  int index;
-  int zaxisID0;
   int dimID = UNDEFID;
   int dimIDs[2];
-  size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
   int nvdimID = UNDEFID;
-  int ilevel = 0;
   int xtype = NC_DOUBLE;
-  int positive;
 
   if ( zaxisInqPrec(zaxisID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
 
@@ -40192,65 +40253,17 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
       }
 
   zaxisInqName(zaxisID, axisname);
-  /*
-  for ( index = 0; index < nzaxis; index++ )
-    {
-      if ( streamptr->zaxisID[index] != UNDEFID )
-        {
-          zaxisID0 = vlistZaxis(vlistID, index);
-          zaxisInqName(zaxisID0, zaxisname0);
-          if ( strcmp(zaxisname0, axisname) == 0 ) ilevel++;
-        }
-    }
-  */
+
   if ( dimID == UNDEFID )
     {
-      char axisname0[CDI_MAX_NAME];
-      char axisname2[CDI_MAX_NAME];
-      int checkname = FALSE;
-      int status;
+      checkZaxisName(axisname, fileID, vlistID, zaxisID, nzaxis);
 
-      /* check that the name is not already defined */
-      checkname = TRUE;
-      ilevel = 0;
+      char dimname[CDI_MAX_NAME+3];
+      dimname[0] = 0;
+      //cdiZaxisInqString(zaxisID, CDI_ZAXIS_DIMNAME, CDI_MAX_NAME, dimname);
+      if ( dimname[0] == 0 ) strcpy(dimname, axisname);
 
-      while ( checkname )
-        {
-          strcpy(axisname2, axisname);
-          if ( ilevel ) sprintf(&axisname2[strlen(axisname2)], "_%d", ilevel+1);
-
-          status = nc_inq_varid(fileID, axisname2, &ncvarid);
-          if ( status != NC_NOERR )
-            {
-              if ( ilevel )
-                {
-                  /* check that the name does not exist for other zaxes */
-                  for ( index = 0; index < nzaxis; index++ )
-                    {
-                      zaxisID0 = vlistZaxis(vlistID, index);
-                      if ( zaxisID != zaxisID0 )
-                        {
-                          zaxisInqName(zaxisID0, axisname0);
-                          if ( strcmp(axisname0, axisname2) == 0 ) break;
-                        }
-                    }
-                  if ( index == nzaxis ) checkname = FALSE;
-                }
-              else
-                {
-                  checkname = FALSE;
-                }
-            }
-
-          if ( checkname ) ilevel++;
-
-          if ( ilevel > 99 ) break;
-        }
-
-      if ( ilevel ) sprintf(&axisname[strlen(axisname)], "_%1d", ilevel+1);
-
-      if ( type == ZAXIS_REFERENCE )
-	cdfDefZaxisUUID(streamptr, zaxisID);
+      if ( type == ZAXIS_REFERENCE ) cdfDefZaxisUUID(streamptr, zaxisID);
 
       if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
         {
@@ -40258,48 +40271,45 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
         }
       else
         {
-          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+          dimID = checkDimName(fileID, dimlen, dimname);
 
-          if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
+          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-          zaxisInqLongname(zaxisID, longname);
-          zaxisInqUnits(zaxisID, units);
-          zaxisInqStdname(zaxisID, stdname);
+          if ( ndims && dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
 
           cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
 
-          if ( (len = strlen(stdname)) )
-            cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-          if ( (len = strlen(longname)) )
-            cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-          if ( (len = strlen(units)) )
-            cdf_put_att_text(fileID, ncvarid, "units", len, units);
-
-	  positive = zaxisInqPositive(zaxisID);
-	  if ( positive == POSITIVE_UP )
-	    {
-	      strcpy(tmpname, "up");
-	      cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
-	    }
-	  else if ( positive == POSITIVE_DOWN )
-	    {
-	      strcpy(tmpname, "down");
-	      cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
-	    }
+          cdfPutGridStdAtts(fileID, ncvarid, zaxisID, &gridInqsZ);
 
+          {
+            int positive = zaxisInqPositive(zaxisID);
+            static const char positive_up[] = "up",
+              positive_down[] = "down";
+            static const struct attTxtTab tab[2] = {
+              { positive_up, sizeof (positive_up) - 1 },
+              { positive_down, sizeof (positive_down) - 1 },
+            };
+            if ( positive == POSITIVE_UP || positive == POSITIVE_DOWN )
+              {
+                size_t select = positive == POSITIVE_DOWN;
+                cdf_put_att_text(fileID, ncvarid, "positive",
+                                 tab[select].txtLen, tab[select].txt);
+              }
+          }
           cdf_put_att_text(fileID, ncvarid, "axis", 1, "Z");
 
 	  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
             {
               size_t nvertex = 2;
-	      if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-		cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+	      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+		cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
 
 	      if ( nvdimID != UNDEFID )
 		{
-		  strcat(axisname, "_");
-		  strcat(axisname, BNDS_NAME);
-		  if ( ndims ) dimIDs[0] = dimID;
+                  size_t axisnameLen = strlen(axisname);
+                  axisname[axisnameLen] = '_';
+                  memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
+		  dimIDs[0] = dimID;
 		  dimIDs[ndims] = nvdimID;
 		  cdf_def_var(fileID, axisname, (nc_type) xtype, ndims+1, dimIDs, &ncbvarid);
 		  cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
@@ -40337,8 +40347,8 @@ static
 void cdfDefPole(stream_t *streamptr, int gridID)
 {
   int ncvarid = UNDEFID;
-  char varname[] = "rotated_pole";
-  char mapname[] = "rotated_latitude_longitude";
+  static const char varname[] = "rotated_pole";
+  static const char mapname[] = "rotated_latitude_longitude";
 
   int fileID  = streamptr->fileID;
 
@@ -40351,7 +40361,7 @@ void cdfDefPole(stream_t *streamptr, int gridID)
   int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
   if ( ncerrcode == NC_NOERR )
     {
-      cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
+      cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", sizeof (mapname) - 1, mapname);
       cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole);
       cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole);
       if ( IS_NOT_EQUAL(angle, 0) )
@@ -40749,6 +40759,7 @@ void init_ncvars(long nvars, ncvar_t *ncvars)
       ncvars[ncvarid].zvarid          = UNDEFID;
       ncvars[ncvarid].tvarid          = UNDEFID;
       ncvars[ncvarid].psvarid         = UNDEFID;
+      ncvars[ncvarid].p0varid         = UNDEFID;
       ncvars[ncvarid].ncoordvars      = 0;
       for ( int i = 0; i < MAX_COORDVARS; ++i )
         ncvars[ncvarid].coordvarids[i]  = UNDEFID;
@@ -40917,9 +40928,9 @@ bool isDepthAxis(const char *stdname, const char *longname)
 {
   bool status = false;
 
-  if ( strcmp(stdname, "depth") == 0 ) status = true;
-
-  if ( status == false )
+  if ( strcmp(stdname, "depth") == 0 )
+    status = true;
+  else
     if ( strcmp(longname, "depth_below_sea") == 0 ||
          strcmp(longname, "depth below sea") == 0 )
       {
@@ -40934,9 +40945,9 @@ bool isHeightAxis(const char *stdname, const char *longname)
 {
   bool status = false;
 
-  if ( strcmp(stdname, "height") == 0 ) status = true;
-
-  if ( status == false )
+  if ( strcmp(stdname, "height") == 0 )
+    status = true;
+  else
     if ( strcmp(longname, "height") == 0 ||
          strcmp(longname, "height above the surface") == 0 )
       {
@@ -40951,11 +40962,11 @@ bool unitsIsPressure(const char *units)
 {
   bool status = false;
 
-  if ( memcmp(units, "millibar", 8) == 0 ||
-       memcmp(units, "mb", 2)       == 0 ||
-       memcmp(units, "hectopas", 8) == 0 ||
-       memcmp(units, "hPa", 3)      == 0 ||
-       memcmp(units, "Pa", 2)       == 0 )
+  if ( strncmp(units, "millibar", 8) == 0 ||
+       strncmp(units, "mb", 2)       == 0 ||
+       strncmp(units, "hectopas", 8) == 0 ||
+       strncmp(units, "hPa", 3)      == 0 ||
+       strncmp(units, "Pa", 2)       == 0 )
     {
       status = true;
     }
@@ -40964,15 +40975,19 @@ bool unitsIsPressure(const char *units)
 }
 
 static
-void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid)
+int scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid, int *avarid, int *p0varid)
 {
+  int status = 0;
   *apvarid = -1;
   *bvarid  = -1;
   *psvarid = -1;
-  const int attstringlen = 8192; char attstring[8192];
+  *avarid  = -1;
+  *p0varid = -1;
+  enum { attstringlen = 8192 }; char attstring[attstringlen];
   cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring);
   if ( strcmp(attstring, "p = ap + b*ps") == 0 )
     {
+      status = 1;
       int lstop = FALSE;
       int dimvarid;
       cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
@@ -40994,8 +41009,8 @@ void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int
           if ( *pstring == 0 ) lstop = TRUE;
           *pstring++ = 0;
 
-          int status = nc_inq_varid(ncid, varname, &dimvarid);
-          if ( status == NC_NOERR )
+          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
+          if ( status_nc == NC_NOERR )
             {
               if      ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid;
               else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
@@ -41003,12 +41018,54 @@ void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int
             }
           else if ( strcmp(tagname, "ps:") != 0 )
             {
-              Warning("%s - %s", nc_strerror(status), varname);
+              Warning("%s - %s", nc_strerror(status_nc), varname);
             }
 
           if ( lstop ) break;
         }
     }
+  else if ( strcmp(attstring, "xxxp = a*p0 + b*ps") == 0 )
+    {
+      status = 2;
+      int lstop = FALSE;
+      int dimvarid;
+      cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
+      char *pstring = attstring;
+
+      for ( int i = 0; i < 4; i++ )
+        {
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *tagname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = TRUE;
+          *pstring++ = 0;
+
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *varname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = TRUE;
+          *pstring++ = 0;
+
+          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
+          if ( status_nc == NC_NOERR )
+            {
+              if      ( strcmp(tagname, "a:")  == 0 ) *avarid  = dimvarid;
+              else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
+              else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
+              else if ( strcmp(tagname, "p0:") == 0 ) *p0varid = dimvarid;
+            }
+          else if ( strcmp(tagname, "ps:") != 0 )
+            {
+              Warning("%s - %s", nc_strerror(status_nc), varname);
+            }
+
+          if ( lstop ) break;
+        }
+    }
+
+  return status;
 }
 
 static
@@ -41027,28 +41084,37 @@ bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, con
       int dimid = ncvar->dimids[0];
       size_t dimlen = ncdims[dimid].len;
 
-      int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1;
+      int ret;
+      int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1, avarid1 = -1, p0varid1 = -1;
       if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
-        scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1);
+        ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1, &avarid1, &p0varid1);
       if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE;
       if ( bvarid1  != -1 ) ncvars[bvarid1].isvar  = FALSE;
       if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1;
+      if ( avarid1  != -1 ) ncvars[avarid1].isvar = FALSE;
+      if ( p0varid1 != -1 ) ncvar->p0varid = p0varid1;
 
       if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms )
         {
           ncfvarid = ncvar->bounds;
-          int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1;
+          int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1, avarid2 = -1, p0varid2 = -1;
+          ret = 0;
           if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
-            scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2);
-          if ( apvarid2 != -1 && bvarid2 != -1 )
+            ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2, &avarid2, &p0varid2);
+          if ( ret == 1 ) avarid2 = apvarid2;
+          if ( avarid2 != -1 && bvarid2 != -1 )
             {
-              ncvars[apvarid2].isvar = FALSE;
+              ncvars[avarid2].isvar = FALSE;
               ncvars[bvarid2].isvar  = FALSE;
 
-              if ( dimid == ncvars[apvarid2].dimids[0] && ncdims[ncvars[apvarid2].dimids[1]].len == 2 )
+              if ( dimid == ncvars[avarid2].dimids[0] && ncdims[ncvars[avarid2].dimids[1]].len == 2 )
                 {
+                  double px = 1;
+                  if ( ret == 2 && p0varid1 == p0varid2 )
+                    cdf_get_var_double(ncid, p0varid2, &px);
+
                   double abuf[dimlen*2], bbuf[dimlen*2];
-                  cdf_get_var_double(ncid, apvarid2, abuf);
+                  cdf_get_var_double(ncid, avarid2, abuf);
                   cdf_get_var_double(ncid, bvarid2, bbuf);
                   /*
                   for ( int i = 0; i < dimlen; ++i )
@@ -41064,6 +41130,9 @@ bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, con
                   vct[dimlen]     = abuf[dimlen*2-1];
                   vct[dimlen*2+1] = bbuf[dimlen*2-1];
 
+                  if ( ret == 2 && IS_NOT_EQUAL(px, 1) )
+                    for ( size_t i = 0; i < dimlen+1; ++i ) vct[i] *= px;
+
                   ncvar->vct = vct;
                   ncvar->vctsize = vctsize;
                 }
@@ -41199,7 +41268,6 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 #if  defined  (HAVE_NETCDF4)
       if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 )
         {
-          char buf[CDI_MAX_NAME];
           int shuffle, deflate, deflate_level;
           size_t chunks[nvdims];
           int storage_in;
@@ -41218,14 +41286,19 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                       for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]);
                       fprintf(stderr, "\n");
                     }
-                  strcat(ncvars[ncvarid].extra, "chunks=");
-                  for ( int i = nvdims-1; i >= 0; --i )
-                    {
-                      sprintf(buf, "%ld", (long) chunks[i]);
-                      strcat(ncvars[ncvarid].extra, buf);
-                      if ( i > 0 ) strcat(ncvars[ncvarid].extra, "x");
-                    }
-                  strcat(ncvars[ncvarid].extra, " ");
+                  {
+                    char *buf = ncvars[ncvarid].extra;
+                    size_t pos = strlen(buf);
+                    static const char prefix[] = "chunks=";
+                    memcpy(buf + pos, prefix, sizeof (prefix));
+                    pos += sizeof (prefix) - 1;
+                    for ( int i = nvdims-1; i >= 0; --i )
+                      {
+                        pos += (size_t)(sprintf(buf + pos, "%zu%s", chunks[i],
+                                                i > 0 ? "x" : ""));
+                      }
+                    buf[pos] = ' '; buf[pos + 1] = 0;
+                  }
                 }
             }
         }
@@ -41459,17 +41532,15 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
             }
           else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
             {
-              char *cell_measures = NULL, *cell_var = NULL;
-
               cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
               char *pstring = attstring;
 
               while ( isspace((int) *pstring) ) pstring++;
-              cell_measures = pstring;
+              char *cell_measures = pstring;
               while ( isalnum((int) *pstring) ) pstring++;
               *pstring++ = 0;
               while ( isspace((int) *pstring) ) pstring++;
-              cell_var = pstring;
+              char *cell_var = pstring;
               while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++;
               *pstring++ = 0;
               /*
@@ -41522,8 +41593,6 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
           */
           else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
             {
-              int status;
-              char *varname = NULL;
               int lstop = FALSE;
               int dimvarid;
 
@@ -41534,12 +41603,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 {
                   while ( isspace((int) *pstring) ) pstring++;
                   if ( *pstring == 0 ) break;
-                  varname = pstring;
+                  char *varname = pstring;
                   while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
                   if ( *pstring == 0 ) lstop = TRUE;
                   *pstring++ = 0;
 
-                  status = nc_inq_varid(ncid, varname, &dimvarid);
+                  int status = nc_inq_varid(ncid, varname, &dimvarid);
                   if ( status == NC_NOERR )
                     {
                       cdfSetVar(ncvars, dimvarid, FALSE);
@@ -41569,8 +41638,6 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
             }
           else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
             {
-              int status;
-              char *varname = NULL;
               int lstop = FALSE;
               int dimvarid;
 
@@ -41581,12 +41648,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 {
                   while ( isspace((int) *pstring) ) pstring++;
                   if ( *pstring == 0 ) break;
-                  varname = pstring;
+                  char *varname = pstring;
                   while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
                   if ( *pstring == 0 ) lstop = TRUE;
                   *pstring++ = 0;
 
-                  status = nc_inq_varid(ncid, varname, &dimvarid);
+                  int status = nc_inq_varid(ncid, varname, &dimvarid);
                   if ( status == NC_NOERR )
                     {
                       cdfSetVar(ncvars, dimvarid, FALSE);
@@ -41651,8 +41718,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( ncvars[ncvarid].lvalidrange == FALSE )
                 {
                   extern int cdiIgnoreValidRange;
-                  int lignore = FALSE;
-                  if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
                   if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
                     {
                       cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange);
@@ -41672,8 +41738,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( ncvars[ncvarid].lvalidrange == FALSE )
                 {
                   extern int cdiIgnoreValidRange;
-                  int lignore = FALSE;
-                  if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
                   if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
                     {
                       cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]);
@@ -41690,8 +41755,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( ncvars[ncvarid].lvalidrange == FALSE )
                 {
                   extern int cdiIgnoreValidRange;
-                  int lignore = FALSE;
-                  if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
                   if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
                     {
                       cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]);
@@ -42726,6 +42790,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	{
           int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
 	  int xdimid = -1, ydimid = -1;
+          int vdimid = -1;
 	  int islon = 0, islat = 0;
 	  int nxdims = 0, nydims = 0;
           size_t size = 0;
@@ -43101,7 +43166,8 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 			int nbdims = ncvars[ncvars[xvarid].bounds].ndims;
 			if ( nbdims == 2 || nbdims == 3 )
 			  {
-			    size_t nvertex = ncdims[ncvars[ncvars[xvarid].bounds].dimids[nbdims-1]].len;
+                            vdimid = ncvars[ncvars[xvarid].bounds].dimids[nbdims-1];
+			    size_t nvertex = ncdims[vdimid].len;
 			    grid->nvertex = (int)nvertex;
                             if (CDI_netcdf_lazy_grid_load)
                               {
@@ -43146,9 +43212,8 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
                               }
                             else
                               {
-                                int vid
-                                  = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1];
-                                size_t nvertex = ncdims[vid].len;
+                                vdimid = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1];
+                                size_t nvertex = ncdims[vdimid].len;
                                 /*
                                   if ( nvertex != grid->nvertex )
                                   Warning("nvertex problem! nvertex x %d, nvertex y %d",
@@ -43204,7 +43269,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	      }
 	    }
 
-          if (grid->type != ncvars[ncvarid].gridtype)
+          if ( grid->type != ncvars[ncvarid].gridtype )
             {
               int gridtype = ncvars[ncvarid].gridtype;
               grid->type = gridtype;
@@ -43423,6 +43488,13 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
           if ( xdimid == -1 && ydimid == -1 && grid->size == 1 )
             gridDefHasDims(ncvars[ncvarid].gridID, FALSE);
 
+          if ( xdimid != -1 )
+            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_XDIMNAME, (int)(strlen(ncdims[xdimid].name)+1), ncdims[xdimid].name);
+          if ( ydimid != -1 )
+            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_YDIMNAME, (int)(strlen(ncdims[ydimid].name)+1), ncdims[ydimid].name);
+          if ( vdimid != -1 )
+            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_VDIMNAME, (int)(strlen(ncdims[vdimid].name)+1), ncdims[vdimid].name);
+
 	  if ( CDI_Debug )
 	    Message("gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid, ncvars[ncvarid].name);
 
@@ -43652,6 +43724,12 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
           if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive);
           if ( is_scalar ) zaxisDefScalar(ncvars[ncvarid].zaxisID);
 
+          if ( zdimid != -1 )
+            cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_DIMNAME, (int)(strlen(ncdims[zdimid].name)+1), ncdims[zdimid].name);
+          /*
+          if ( vdimid != -1 )
+            cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_VDIMNAME, strlen(ncdims[vdimid].name)+1, ncdims[vdimid].name);
+          */
 	  Free(zvar);
 	  Free(lbounds);
 	  Free(ubounds);
@@ -46467,7 +46545,7 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
   int timerange = -1;
   int year, month, day, hour, minute, second;
   int julday1, secofday1, julday2, secofday2, days, secs;
-  int ip, ip1 = 0, ip2 = 0;
+  int ip1 = 0, ip2 = 0;
 
   cdiDecodeDate(rdate, &year, &month, &day);
   cdiDecodeTime(rtime, &hour, &minute, &second);
@@ -46481,7 +46559,9 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
 
   if ( !(int)(fmod(days*86400.0 + secs, factor)) )
     {
-      ip = (int) ((days*86400.0 + secs)/factor);
+      int ip = (int) ((days*86400.0 + secs)/factor);
+
+      if ( (ip > 255) && (tsteptype == TSTEP_INSTANT) ) tsteptype = TSTEP_INSTANT3;
 
       switch ( tsteptype )
 	{
@@ -46492,14 +46572,14 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
 	case TSTEP_ACCUM:    timerange =  4; ip1 = 0;  ip2 = ip; break;
 	case TSTEP_DIFF:     timerange =  5; ip1 = 0;  ip2 = ip; break;
 	case TSTEP_INSTANT3:
-	default:             timerange = 10; ip1 = ip/256; ip2 = ip%256;  break;
+	default:             timerange = 10; ip1 = ip/256; ip2 = ip%256; break;
 	}
     }
 
   *pip1 = ip1;
   *pip2 = ip2;
 
-  return (timerange);
+  return timerange;
 }
 
 static
@@ -46636,7 +46716,6 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg,
 static
 void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridID)
 {
-  int gridtype;
   bool lcurvi = false;
   static bool lwarning = true;
 
@@ -46644,7 +46723,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 
   ISEC1_Sec2Or3Flag = 128;
 
-  gridtype = gridInqType(gridID);
+  int gridtype = gridInqType(gridID);
 
   ISEC1_GridDefinition = 255;
 
@@ -46700,10 +46779,11 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	int nlon = 0, nlat;
 	double xfirst = 0, xlast = 0, xinc = 0;
 	double yfirst = 0, ylast = 0, yinc = 0;
+        bool isRotated = gridIsRotated(gridID);
 
 	if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
           ISEC2_GridType = GRIB1_GTYPE_GAUSSIAN;
-        else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+        else if ( gridtype == GRID_LONLAT && isRotated )
 	  ISEC2_GridType = GRIB1_GTYPE_LATLON_ROT;
 	else
 	  ISEC2_GridType = GRIB1_GTYPE_LATLON;
@@ -46726,10 +46806,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	    else
 	      {
 		xfirst = gridInqXval(gridID,      0);
-		if ( lcurvi )
-		  xlast  = gridInqXval(gridID, nlon*nlat-1);
-		else
-		  xlast  = gridInqXval(gridID, nlon-1);
+                xlast  = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1);
 		xinc   = gridInqXinc(gridID);
 	      }
 	  }
@@ -46741,12 +46818,8 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	else
 	  {
 	    yfirst = gridInqYval(gridID,      0);
-	    if ( lcurvi )
-	      ylast  = gridInqYval(gridID, nlon*nlat-1);
-	    else
-	      ylast  = gridInqYval(gridID, nlat-1);
-	    yinc   = gridInqYinc(gridID);
-	    if ( yinc < 0 ) yinc = -yinc;
+            ylast  = gridInqYval(gridID, (lcurvi ? nlon*nlat : nlat) - 1);
+	    yinc   = fabs(gridInqYinc(gridID));
 	  }
 
 	ISEC2_NumLon   = nlon;
@@ -46784,12 +46857,9 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
 	  if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
 
-	if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 )
-	  ISEC2_ResFlag = 0;
-	else
-	  ISEC2_ResFlag = 128;
+        ISEC2_ResFlag = ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 ) ? 0 : 128;
 
-	if ( gridIsRotated(gridID) )
+	if ( isRotated )
 	  {
 	    ISEC2_LatSP = - (int)lround(gridInqYpole(gridID) * 1000);
 	    ISEC2_LonSP =   (int)lround((gridInqXpole(gridID) + 180) * 1000);
@@ -48656,13 +48726,13 @@ typedef struct  {
   int                     subtype;               /* subtype kind: TILES, ... */
   int                     nentries;              /* counter: total no. of entries in list */
 
+  /* currently active subtype, e.g. GRIB2 tile index (for example for
+     stream/vlist accesses): */
+  int                     active_subtype_index;
   struct subtype_entry_t  globals;               /* global attributes */
 
   /* list of subtype entries, e.g. the list of tiles, ordered by entry->self. */
   struct subtype_entry_t *entries;
-  /* currently active subtype, e.g. GRIB2 tile index (for example for
-     stream/vlist accesses): */
-  int                     active_subtype_index;
 } subtype_t;
 
 
@@ -48753,7 +48823,7 @@ int gribapiGetZaxisType(long editionNumber, int grib_ltype)
       zaxistype = grib2ltypeToZaxisType(grib_ltype);
     }
 
-  return (zaxistype);
+  return zaxistype;
 }
 
 static
@@ -48773,7 +48843,7 @@ int getTimeunits(long unitsOfTime)
     default:  timeunits = TUNIT_HOUR;    break;
     }
 
-  return (timeunits);
+  return timeunits;
 }
 
 static
@@ -48795,7 +48865,7 @@ double timeunit_factor(int tu1, int tu2)
         }
     }
 
-  return (factor);
+  return factor;
 }
 
 static
@@ -48810,7 +48880,7 @@ int gribapiGetTimeUnits(grib_handle *gh)
 
   timeunits = getTimeunits(unitsOfTime);
 
-  return (timeunits);
+  return timeunits;
 }
 
 static
@@ -48938,7 +49008,7 @@ int gribapiGetValidityDateTime(grib_handle *gh, int *vdate, int *vtime)
       }
     }
 
-  return (tstepRange);
+  return tstepRange;
 }
 
 static
@@ -49341,7 +49411,7 @@ static compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype
   memcpy(compVar.name, name, len);
   compVar.tiles = tiles_data;
 
-  return (compVar);
+  return compVar;
 }
 
 static
@@ -49598,7 +49668,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
   streamptr->rtsteps = 1;
 
-  if ( nrecs == 0 ) return (CDI_EUFSTRUCT);
+  if ( nrecs == 0 ) return CDI_EUFSTRUCT;
 
   cdi_generate_vars(streamptr);
 
@@ -49661,7 +49731,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
         }
     }
 
-  return (0);
+  return 0;
 }
 
 
@@ -49794,7 +49864,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
       if ( recID == nrecords )
 	{
 	  gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       if ( streamptr->tsteps[tsID].records[recID].used )
@@ -49828,7 +49898,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 		  tsID, recID,
 		  streamptr->tsteps[tsID].records[recID].param, param,
 		  streamptr->tsteps[tsID].records[recID].ilevel, level1);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->tsteps[1].records[recID].position = recpos;
@@ -49883,7 +49953,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
   streamptr->record->buffer     = gribbuffer;
   streamptr->record->buffersize = buffersize;
 
-  return (rstatus);
+  return rstatus;
 }
 
 
@@ -50029,7 +50099,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	      gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
 
 	      if ( cdiInventoryMode == 1 )
-		return (CDI_EUFSTRUCT);
+		return CDI_EUFSTRUCT;
 	      else
 		continue;
 	    }
@@ -50086,7 +50156,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	{
 	  gribWarning("Paramameter not found!", nrecs_scanned, tsID+1, varname, streamptr->tsteps[tsID].records[recID].param,
                       streamptr->tsteps[tsID].records[recID].ilevel, streamptr->tsteps[tsID].records[recID].ilevel2);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->rtsteps++;
@@ -50299,11 +50369,42 @@ int getTimeunitFactor(int timeunit)
     default:            factor =  3600;  break;
     }
 
-  return (factor);
+  return factor;
+}
+
+static
+int grib2ProDefTempHasStatisticalDef(int proDefTempNum)
+{
+  int hasStatisticalDef = 0;
+
+  switch (proDefTempNum)
+    {
+      case 8:
+      case 9:
+      case 10:
+      case 11:
+      case 12:
+      case 13:
+      case 14:
+      case 34:
+      case 42:
+      case 43:
+      case 46:
+      case 47:
+      case 61:
+      case 91:
+      case 1001:
+      case 1101:
+      case 40034:
+               hasStatisticalDef = 1;  break;
+      default: hasStatisticalDef = 0;  break;
+    }
+
+  return hasStatisticalDef;
 }
 
 static
-void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
+void gribapiDefStepUnits(int editionNumber, grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
 {
   long unitsOfTime;
 
@@ -50322,9 +50423,19 @@ void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int g
   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);
+      if ( editionNumber == 1 )
+        {
+          GRIB_CHECK(my_grib_set_long(gh, "unitOfTimeRange", unitsOfTime), 0);
+        }
+      else if ( grib2ProDefTempHasStatisticalDef(proDefTempNum) )
+        {
+          GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0);
+          //  GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+        }
+      else
+        {
+          GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+        }
     }
 }
 
@@ -50376,7 +50487,7 @@ int gribapiDefSteptype(int editionNumber, grib_handle *gh, int productDefinition
       GRIB_CHECK(my_grib_set_string(gh, "stepType", stepType, &len), 0);
     }
 
-  return ((int)proDefTempNum);
+  return (int)proDefTempNum;
 }
 
 static
@@ -50418,7 +50529,7 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
     {
       int proDefTempNum = gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
 
-      gribapiDefStepUnits(gh, timeunit, proDefTempNum, gcinit);
+      gribapiDefStepUnits(editionNumber, gh, timeunit, proDefTempNum, gcinit);
 
       endStep = (int) ((days*86400.0 + secs)/factor);
 
@@ -50442,7 +50553,7 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
       status = 0;
     }
 
-  return (status);
+  return status;
 }
 
 static
@@ -50487,6 +50598,38 @@ void gribapiDefTime(int editionNumber, int productDefinitionTemplate, int typeOf
     }
 }
 
+struct gribApiMsg {
+  size_t msgLen;
+  const char *msg;
+};
+
+static struct gribApiMsg
+getGribApiCompTypeMsg(grib_handle *gh, int comptype, int gridsize)
+{
+  const char *mesg;
+  size_t len;
+  if ( comptype == COMPRESS_JPEG && gridsize > 1 )
+    {
+      static const char mesg_grid_jpeg[] = "grid_jpeg";
+      len = sizeof (mesg_grid_jpeg) - 1;
+      mesg = mesg_grid_jpeg;
+    }
+  else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
+    {
+      static const char mesg_grid_ccsds[] = "grid_ccsds";
+      len = sizeof (mesg_grid_ccsds) - 1;
+      mesg = mesg_grid_ccsds;
+    }
+  else
+    {
+      static const char mesg_simple[] = "grid_simple";
+      len = sizeof (mesg_simple) - 1;
+      mesg = mesg_simple;
+    }
+  return (struct gribApiMsg){ .msgLen = len, .msg = mesg };
+}
+
+
 static
 void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, int lieee, int datatype, int nmiss, int gcinit)
 {
@@ -50543,24 +50686,11 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 
       if ( comptype )
         {
-          if ( comptype == COMPRESS_JPEG && gridsize > 1 )
-            {
-              static const char mesg[] = "grid_jpeg";
-              size_t len = sizeof (mesg) - 1;
-              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-            }
-          else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
-            {
-              static const char mesg[] = "grid_ccsds";
-              size_t len = sizeof (mesg) - 1;
-              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-            }
-          else
-            {
-              static const char mesg[] = "grid_simple";
-              size_t len = sizeof (mesg) - 1;
-              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-            }
+          struct gribApiMsg gaMsg
+            = getGribApiCompTypeMsg(gh, comptype, gridsize);
+          size_t len = gaMsg.msgLen;
+          const char *mesg = gaMsg.msg;
+          GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
         }
     }
 
@@ -50577,30 +50707,35 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	double yfirst = 0, ylast = 0, yinc = 0;
 	double latIncr;
 
-	if ( gridtype == GRID_GAUSSIAN )
-	  {
-            static const char mesg[] = "regular_gg";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-	  }
-	else if ( gridtype == GRID_GAUSSIAN_REDUCED )
-	  {
-            static const char mesg[] = "reduced_gg";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-	  }
-	else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
-	  {
-            static const char mesg[] = "rotated_ll";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-	  }
-	else
-	  {
-            static const char mesg[] = "regular_ll";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+        {
+          const char *mesg;
+          size_t len;
+          if ( gridtype == GRID_GAUSSIAN )
+            {
+              static const char mesg_gaussian[] = "regular_gg";
+              len = sizeof (mesg_gaussian) - 1;
+              mesg = mesg_gaussian;
+            }
+          else if ( gridtype == GRID_GAUSSIAN_REDUCED )
+            {
+              static const char mesg_gaussian_reduced[] = "reduced_gg";
+              len = sizeof (mesg_gaussian_reduced) - 1;
+              mesg = mesg_gaussian_reduced;
+            }
+          else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+            {
+              static const char mesg_rot_lonlat[] = "rotated_ll";
+              len = sizeof (mesg_rot_lonlat) - 1;
+              mesg = mesg_rot_lonlat;
+            }
+          else
+            {
+              static const char mesg_regular_ll[] = "regular_ll";
+              len = sizeof (mesg_regular_ll) - 1;
+              mesg = mesg_regular_ll;
 	  }
+          GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+        }
 
 	int nlon = gridInqXsize(gridID);
 	int nlat = gridInqYsize(gridID);
@@ -50714,38 +50849,28 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 
         if ( editionNumber != 2 ) { lieee = 0; comptype = 0; }
 
-        if ( lieee )
-          {
-            static const char mesg[] = "grid_ieee";
-            size_t len = sizeof (mesg) -1;
-            GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+        {
+          const char *mesg;
+          size_t len;
+          if ( lieee )
+            {
+              static const char mesg_grid_ieee[] = "grid_ieee";
+              len = sizeof (mesg_grid_ieee) - 1;
+              mesg = mesg_grid_ieee;
+            }
+          else
+            {
+              struct gribApiMsg gaMsg
+                = getGribApiCompTypeMsg(gh, comptype, gridsize);
+              len = gaMsg.msgLen;
+              mesg = gaMsg.msg;
+            }
+          GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+          if ( lieee )
+            GRIB_CHECK(my_grib_set_long(gh, "precision",
+                                        datatype == DATATYPE_FLT64 ? 2 : 1), 0);
 
-	    if ( datatype == DATATYPE_FLT64 )
-	      GRIB_CHECK(my_grib_set_long(gh, "precision", 2), 0);
-	    else
-	      GRIB_CHECK(my_grib_set_long(gh, "precision", 1), 0);
-          }
-        else
-	  {
-            if ( comptype == COMPRESS_JPEG && gridsize > 1 )
-              {
-                static const char mesg[] = "grid_jpeg";
-                size_t len = sizeof (mesg) -1;
-                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-              }
-            else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
-              {
-                static const char mesg[] = "grid_ccsds";
-                size_t len = sizeof (mesg) -1;
-                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-              }
-            else
-              {
-                static const char mesg[] = "grid_simple";
-                size_t len = sizeof (mesg) -1;
-                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-              }
-	  }
+        }
 
 	break;
       }
@@ -62297,6 +62422,7 @@ void cdiCreateTimesteps(stream_t *streamptr)
 #include <float.h>
 #include <inttypes.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 
@@ -62481,6 +62607,7 @@ void cdiCreateUUID(unsigned char *uuid)
 {
   static int uuid_seeded = 0;
   static char uuid_rand_state[31 * sizeof (long)];
+#ifndef _SX
   char *caller_rand_state;
   if (uuid_seeded)
     caller_rand_state = setstate(uuid_rand_state);
@@ -62500,11 +62627,17 @@ void cdiCreateUUID(unsigned char *uuid)
     }
   for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
     uuid[i] = (unsigned char)random();
+#else
+  for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
+    uuid[i] = (unsigned char)lrand48();
+#endif
   /* encode variant into msb of octet 8 */
   uuid[8] = (unsigned char)((uuid[8] & 0x3f) | (1 << 7));
   /* encode version 4 ((pseudo-)random uuid) into msb of octet 7 */
   uuid[7] = (unsigned char)((uuid[7] & 0x0f) | (4 << 4));
+#ifndef _SX
   setstate(caller_rand_state);
+#endif
 }
 #endif
 
@@ -66001,7 +66134,6 @@ vlistAttsUnpack(int vlistID, int varID,
 
 
 #if  defined  (HAVE_LIBGRIB_API)
-
 #  include <grib_api.h>
 #endif
 
@@ -66156,7 +66288,8 @@ int vlistDefVarTiles(int vlistID, int gridID, int zaxisID, int tsteptype, int ti
     @Item  gridID    Grid ID, from a previous call to @fref{gridCreate}.
     @Item  zaxisID   Z-axis ID, from a previous call to @fref{zaxisCreate}.
     @Item  tsteptype One of the set of predefined CDI timestep types.
-                     The valid CDI timestep types are @func{TSTEP_CONSTANT} and @func{TSTEP_INSTANT}.
+                     The valid CDI timestep types are @func{TSTEP_CONSTANT}, @func{TSTEP_INSTANT},
+                     @func{TSTEP_ACCUM}, @func{TSTEP_AVG}, @func{TSTEP_MAX}, @func{TSTEP_MIN} and @func{TSTEP_SD}.
 
 @Description
 The function @func{vlistDefVar} adds a new variable to vlistID.
@@ -66287,10 +66420,10 @@ void vlistInqVar(int vlistID, int varID, int *gridID, int *zaxisID, int *tstepty
     @Item  varID    Variable identifier.
 
 @Description
-The function @func{vlistInqVarGrid} returns the grid ID of a variable.
+The function @func{vlistInqVarGrid} returns the grid ID of a Variable.
 
 @Result
- at func{vlistInqVarGrid} returns the grid ID of the variable.
+ at func{vlistInqVarGrid} returns the grid ID of the Variable.
 
 @EndFunction
 */
@@ -67214,7 +67347,26 @@ void vlistDefVarTsteptype(int vlistID, int varID, int tsteptype)
     }
 }
 
+/*
+ at Function  vlistInqVarTsteptype
+ at Title     Get the timestep type of a Variable
 
+ at Prototype int vlistInqVarTsteptype(int vlistID, int varID)
+ at Parameter
+    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
+    @Item  varID    Variable identifier.
+
+ at Description
+The function @func{vlistInqVarTsteptype} returns the timestep type of a Variable.
+
+ at Result
+ at func{vlistInqVarTsteptype} returns the timestep type of the Variable,
+one of the set of predefined CDI timestep types.
+The valid CDI timestep types are @func{TSTEP_CONSTANT}, @func{TSTEP_INSTANT},
+ at func{TSTEP_ACCUM}, @func{TSTEP_AVG}, @func{TSTEP_MAX}, @func{TSTEP_MIN} and @func{TSTEP_SD}.
+
+ at EndFunction
+*/
 int vlistInqVarTsteptype(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
@@ -68305,7 +68457,8 @@ enum {
 
 
 typedef struct {
-  unsigned char positive;
+  char     dimname[CDI_MAX_NAME];
+  char     vdimname[CDI_MAX_NAME];
   char     name[CDI_MAX_NAME];
   char     longname[CDI_MAX_NAME];
   char     stdname[CDI_MAX_NAME];
@@ -68324,6 +68477,7 @@ typedef struct {
   int      size;
   int      direction;
   int      vctsize;
+  unsigned positive;
   double  *vct;
   int      number;   /* Reference number to a generalized Z-axis */
   int      nhlev;
@@ -68381,6 +68535,8 @@ void zaxisDefaultValue(zaxis_t *zaxisptr)
   zaxisptr->name[0]     = 0;
   zaxisptr->longname[0] = 0;
   zaxisptr->stdname[0]  = 0;
+  zaxisptr->dimname[0]  = 0;
+  zaxisptr->vdimname[0] = 0;
   zaxisptr->units[0]    = 0;
   zaxisptr->psname[0]   = 0;
   zaxisptr->vals        = NULL;
@@ -68593,6 +68749,113 @@ void zaxisName(int zaxistype, char *zaxisname)
   strcpy(zaxisname, zaxisNamePtr(zaxistype));
 }
 
+static inline
+void zaxisSetString(char *zaxisstrname, const char *name, size_t len)
+{
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(zaxisstrname, name, len);
+  zaxisstrname[len - 1] = 0;
+}
+
+static inline
+void zaxisGetString(char *name, const char *zaxisstrname, size_t len)
+{
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(name, zaxisstrname, len);
+  name[len - 1] = 0;
+}
+
+static
+char *zaxis_key_to_string(zaxis_t *zaxisptr, int key)
+{
+  char *zaxisstring = NULL;
+
+  switch (key)
+    {
+    case CDI_ZAXIS_DIMNAME:  zaxisstring = zaxisptr->dimname; break;
+    case CDI_ZAXIS_VDIMNAME: zaxisstring = zaxisptr->vdimname; break;
+    }
+
+  return zaxisstring;
+}
+
+/*
+ at Function  cdiZaxisDefString
+ at Title     Define a CDI Z-axis string value from a key
+
+ at Prototype int cdiZaxisDefString(int zaxisID, int key, int size, const char *mesg)
+ at Parameter
+    @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
+    @Item  key      The key to be searched
+    @Item  size     The allocated length of the string on input
+    @Item  mesg     The address of a string where the data will be read
+
+ at Description
+The function @func{cdiZaxisDefString} defines a CDI Z-axis string value from a key.
+
+ at Result
+ at func{cdiZaxisDefString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiZaxisDefString(int zaxisID, int key, int size, const char *mesg)
+{
+  if ( size <= 0 || mesg == NULL || *mesg == 0 ) return -1;
+
+  zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
+
+  char *zaxisstring = zaxis_key_to_string(zaxisptr, key);
+  if ( zaxisstring == NULL)
+    {
+      Warning("CDI zaxis string key %d not supported!", key);
+      return -1;
+    }
+
+  zaxisSetString(zaxisstring, mesg, (size_t)size);
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+
+  return 0;
+}
+
+/*
+ at Function  cdiZaxisInqString
+ at Title     Get a CDI Z-axis string value from a key
+
+ at Prototype int cdiZaxisInqString(int zaxisID, int key, int size, char *mesg)
+ at Parameter
+    @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
+    @Item  key      The key to be searched.
+    @Item  size     The allocated length of the string on input.
+    @Item  mesg     The address of a string where the data will be retrieved.
+                    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}.
+
+ at Description
+The function @func{cdiZaxisInqString} return a CDI Z-axis string value from a key.
+
+ at Result
+ at func{cdiZaxisInqString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiZaxisInqString(int zaxisID, int key, int size, char *mesg)
+{
+  if ( size <= 0 || mesg == NULL ) return -1;
+
+  zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
+  const char *zaxisstring = zaxis_key_to_string(zaxisptr, key);
+  if ( zaxisstring == NULL)
+    {
+      Warning("CDI zaxis string key %d not supported!", key);
+      return -1;
+    }
+
+  zaxisGetString(mesg, zaxisstring, (size_t)size);
+
+  return 0;
+}
+
 /*
 @Function  zaxisDefName
 @Title     Define the name of a Z-axis
@@ -68709,6 +68972,12 @@ void zaxisInqName(int zaxisID, char *name)
   strcpy(name, zaxisptr->name);
 }
 
+const char *zaxisInqNamePtr(int zaxisID)
+{
+  zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
+  return zaxisptr->name;
+}
+
 /*
 @Function  zaxisInqLongname
 @Title     Get the longname of a Z-axis
@@ -68797,9 +69066,9 @@ void zaxisDefPositive(int zaxisID, int positive)
 {
   zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
 
-  if (zaxisptr->positive != positive)
+  if (zaxisptr->positive != (unsigned)(positive != 0))
     {
-      zaxisptr->positive = (unsigned char)positive;
+      zaxisptr->positive = (unsigned)(positive != 0);
       reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -68808,7 +69077,7 @@ void zaxisDefPositive(int zaxisID, int positive)
 int zaxisInqPositive(int zaxisID)
 {
   zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
-  return zaxisptr->positive;
+  return (int)zaxisptr->positive;
 }
 
 
@@ -69954,7 +70223,7 @@ void cdiZaxisGetIndexList(unsigned nzaxis, int *zaxisResHs)
  * require-trailing-newline: t
  * End:
  */
-   static const char cdi_libvers[] = "1.7.1" " of " "Feb 19 2016"" " "11:18:00";
+   static const char cdi_libvers[] = "1.7.2rc3" " of " "Apr 18 2016"" " "14:13:00";
 const char *cdiLibraryVersion(void)
 {
   return (cdi_libvers);
@@ -72852,6 +73121,11 @@ FCALLSCSUB2 (gridDefXvals, GRIDDEFXVALS, griddefxvals, INT, DOUBLEV)
 FCALLSCFUN2 (INT, gridInqXvals, GRIDINQXVALS, gridinqxvals, INT, DOUBLEV)
 FCALLSCSUB2 (gridDefYvals, GRIDDEFYVALS, griddefyvals, INT, DOUBLEV)
 FCALLSCFUN2 (INT, gridInqYvals, GRIDINQYVALS, gridinqyvals, INT, DOUBLEV)
+
+/*  CDI grid string key values  */
+
+FCALLSCFUN4 (INT, cdiGridDefString, CDIGRIDDEFSTRING, cdigriddefstring, INT, INT, INT, STRING)
+FCALLSCFUN4 (INT, cdiGridInqString, CDIGRIDINQSTRING, cdigridinqstring, INT, INT, INT, PSTRING)
 FCALLSCSUB2 (gridDefXname, GRIDDEFXNAME, griddefxname, INT, STRING)
 FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING)
 FCALLSCSUB2 (gridDefXlongname, GRIDDEFXLONGNAME, griddefxlongname, INT, STRING)
@@ -72954,6 +73228,11 @@ FCALLSCSUB2 (zaxisDefNumber, ZAXISDEFNUMBER, zaxisdefnumber, INT, INT)
 FCALLSCFUN1 (INT, zaxisInqNumber, ZAXISINQNUMBER, zaxisinqnumber, INT)
 FCALLSCSUB2 (zaxisDefUUID, ZAXISDEFUUID, zaxisdefuuid, INT, PVOID)
 FCALLSCSUB2 (zaxisInqUUID, ZAXISINQUUID, zaxisinquuid, INT, PVOID)
+
+/*  CDI zaxis string key values  */
+
+FCALLSCFUN4 (INT, cdiZaxisDefString, CDIZAXISDEFSTRING, cdizaxisdefstring, INT, INT, INT, STRING)
+FCALLSCFUN4 (INT, cdiZaxisInqString, CDIZAXISINQSTRING, cdizaxisinqstring, INT, INT, INT, PSTRING)
 FCALLSCSUB2 (zaxisDefName, ZAXISDEFNAME, zaxisdefname, INT, STRING)
 FCALLSCSUB2 (zaxisInqName, ZAXISINQNAME, zaxisinqname, INT, PSTRING)
 FCALLSCSUB2 (zaxisDefLongname, ZAXISDEFLONGNAME, zaxisdeflongname, INT, STRING)
diff --git a/libcdi/src/cdipio.inc b/libcdi/src/cdipio.inc
index ab4eba3..9151a81 100644
--- a/libcdi/src/cdipio.inc
+++ b/libcdi/src/cdipio.inc
@@ -1,10 +1,10 @@
 ! This file was automatically generated, don't edit!
 !
-! Fortran interface for CDI library version 1.7.0
+! Fortran interface for CDI library version 1.7.2
 !
 ! Author:
 ! -------
-! Uwe Schulzweida, MPI-MET, Hamburg,   February 2016
+! Uwe Schulzweida, MPI-MET, Hamburg,   April 2016
 !
 
 !
diff --git a/libcdi/src/cgribexlib.c b/libcdi/src/cgribexlib.c
index e824767..8739592 100644
--- a/libcdi/src/cgribexlib.c
+++ b/libcdi/src/cgribexlib.c
@@ -1,7 +1,7 @@
 
-/* Automatically generated by m214003 at 2016-02-19, do not edit */
+/* Automatically generated by m214003 at 2016-06-03, do not edit */
 
-/* CGRIBEXLIB_VERSION="1.7.4" */
+/* CGRIBEXLIB_VERSION="1.7.5" */
 
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined (__clang__)
 #pragma GCC diagnostic push
@@ -367,6 +367,7 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
 #ifndef _GRIB_ENCODE_H
 #define _GRIB_ENCODE_H
 
+#include <limits.h>
 
 #define PutnZero(n) \
 { \
@@ -389,6 +390,11 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
 #define Put2Int(Value)  {ival = Value; if ( ival < 0 ) ival =   0x8000 - ival; Put2Byte(ival);}
 #define Put3Int(Value)  {ival = Value; if ( ival < 0 ) ival = 0x800000 - ival; Put3Byte(ival);}
 
+enum {
+  BitsPerInt = (int) (sizeof(int) * CHAR_BIT),
+};
+
+
 #define Put1Real(Value)          \
 {                                \
   confp3(Value, &exponent, &mantissa, BitsPerInt, 1); \
@@ -402,22 +408,34 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
 #define gribSwapByteOrder_uint16(ui16)  ((uint16_t)((ui16<<8) | (ui16>>8)))
 #endif  /* CODEC_COMMON_H */
 /* 
-icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
+icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -qopenmp -DOMP_SIMD minmax_val.c
  result on hama2 (icc 16.0.0):
      float:
-minmax_val: fmin: -500000  fmax: 499999  time:   0.63s
+minmax_val: fmin: -500000  fmax: 499999  time:   1.22s
+simd      : fmin: -500000  fmax: 499999  time:   1.20s
     double:
-minmax_val: fmin: -500000  fmax: 499999  time:   2.98s
-orig      : fmin: -500000  fmax: 499999  time:   2.83s
-simd      : fmin: -500000  fmax: 499999  time:   2.82s
-avx       : fmin: -500000  fmax: 499999  time:   3.17s
+minmax_val: fmin: -500000  fmax: 499999  time:   2.86s
+orig      : fmin: -500000  fmax: 499999  time:   2.74s
+simd      : fmin: -500000  fmax: 499999  time:   2.70s
+avx       : fmin: -500000  fmax: 499999  time:   2.99s
+
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL -fopenmp -DOMP_SIMD -Wa,-q minmax_val.c
+ result on thunder5 (gcc 6.1.0):
+float:
+minmax_val: fmin: -500000  fmax: 499999  time:   8.25s
+  simd    : fmin: -500000  fmax: 499999  time:   1.24s
+double:
+minmax_val: fmin: -500000  fmax: 499999  time:   2.73s
+  orig    : fmin: -500000  fmax: 499999  time:   9.24s
+  simd    : fmin: -500000  fmax: 499999  time:   2.78s
+  avx     : fmin: -500000  fmax: 499999  time:   2.90s
 
 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL minmax_val.c
  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
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL -fopenmp -DOMP_SIMD -Wa,-q minmax_val.c
  result on thunder5 (gcc 4.8.2):
   orig    : fmin: -500000  fmax: 499999  time:   3.10s
   simd    : fmin: -500000  fmax: 499999  time:   3.10s # omp simd in gcc 4.9
@@ -459,18 +477,24 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL minmax
 #endif
 #endif
 
+#ifndef DISABLE_SIMD
 #if   defined(__GNUC__) && (__GNUC__ >= 4)
 #elif defined(__ICC)    && (__ICC >= 1100)
 #elif defined(__clang__)
 #else
 #define DISABLE_SIMD
 #endif
+#endif
+
+#ifdef DISABLE_SIMD
+#define DISABLE_SIMD_MINMAXVAL
+#endif
 
 #if !defined(TEST_MINMAXVAL)
-#define DISABLE_SIMD
+#define DISABLE_SIMD_MINMAXVAL
 #endif
 
-#if defined(DISABLE_SIMD)
+#ifdef DISABLE_SIMD_MINMAXVAL
 # if defined(ENABLE_AVX)
 #  define _ENABLE_AVX
 # endif
@@ -479,7 +503,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL minmax
 # endif
 #endif
 
-#if !defined(DISABLE_SIMD)
+#ifndef DISABLE_SIMD_MINMAXVAL
 # if defined(__AVX__)
 #  define _ENABLE_AVX
 # endif
@@ -723,6 +747,10 @@ static
 void minmax_val_double_orig(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
 static
 void minmax_val_double_simd(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
+static
+void minmax_val_float(const float *restrict data, long datasize, float *fmin, float *fmax) __attribute__ ((noinline));
+static
+void minmax_val_float_simd(const float *restrict data, size_t datasize, float *fmin, float *fmax) __attribute__ ((noinline));
 #endif
 
 #if defined(GNUC_PUSH_POP)
@@ -805,6 +833,23 @@ void minmax_val_double_simd(const double *restrict data, size_t datasize, double
   *fmin = dmin;
   *fmax = dmax;
 }
+static
+void minmax_val_float_simd(const float *restrict data, size_t datasize, float *fmin, float *fmax)
+{
+  float dmin = *fmin, dmax = *fmax;
+
+#if defined(_OPENMP)
+#pragma omp simd reduction(min:dmin) reduction(max:dmax)
+#endif
+  for ( size_t i = 0; i < datasize; ++i )
+    {
+      dmin = dmin < data[i] ? dmin : data[i];
+      dmax = dmax > data[i] ? dmax : data[i];
+    }
+
+  *fmin = dmin;
+  *fmax = dmax;
+}
 #if defined(GNUC_PUSH_POP)
 #pragma GCC pop_options
 #endif
@@ -942,6 +987,18 @@ int main(void)
       }
     t_end = dtime();
     printf("minmax_val: 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_sp[0];
+	minmax_val_float_simd(data_sp, 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
+
     free(data_sp);
   }
 
@@ -1020,14 +1077,14 @@ int main(void)
 }
 #endif // TEST_MINMAXVAL
 
-#undef DISABLE_SIMD
+#undef DISABLE_SIMD_MINMAXVAL
 #undef _ENABLE_AVX
 #undef _ENABLE_SSE2
 #undef GNUC_PUSH_POP
 /*
 ### new version with gribSwapByteOrder_uint16()
 icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
- result on hama2 (icc 16.0.0):
+ result on hama2 (icc 16.0.2):
    float:
     orig: val1: 1  val2: 1  val3: 2  valn: 66  time: 1.8731s
 unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time: 2.0898s
@@ -1036,14 +1093,15 @@ unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time: 2.0898s
 unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time: 4.30798s
      avx: val1: 1  val2: 1  val3: 2  valn: 66  time: 4.23864s
 
-gcc -g -Wall -O3 -std=c99 -DTEST_ENCODE encode_array.c
- result on hama2 (gcc 5.2.0):
-   float:
-    orig: val1: 1  val2: 1  val3: 2  valn: 66  time: 3.96739s
-unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time: 4.30871s
-  double:
-    orig: val1: 1  val2: 1  val3: 2  valn: 66  time: 6.24448s
-unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time: 8.66679s
+gcc -g -Wall -O3 -march=native -Wa,-q -std=c99 -DTEST_ENCODE encode_array.c
+ result on hama2 (gcc 6.1.0):
+float:
+    orig: val1: 1  val2: 1  val3: 2  valn: 66  time: 2.22871s
+unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time: 2.30281s
+double:
+    orig: val1: 1  val2: 1  val3: 2  valn: 66  time: 4.2669s
+unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time: 4.81643s
+     avx: val1: 1  val2: 1  val3: 2  valn: 66  time: 3.98415s
 
 ###
 icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
@@ -1116,16 +1174,22 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_ENCODE encode_ar
 
 #include <stdint.h>
 
+#ifndef DISABLE_SIMD
 #if   defined(__GNUC__) && (__GNUC__ >= 4)
 #elif defined(__ICC)    && (__ICC >= 1100)
 #elif defined(__clang__)
 #else
 #define DISABLE_SIMD
 #endif
-
-//#define DISABLE_SIMD
+#endif
 
 #ifdef DISABLE_SIMD
+#define DISABLE_SIMD_ENCODE
+#endif
+
+//#define DISABLE_SIMD_ENCODE
+
+#ifdef DISABLE_SIMD_ENCODE
 # ifdef ENABLE_AVX
 #  define _ENABLE_AVX
 # endif
@@ -1134,7 +1198,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_ENCODE encode_ar
 # endif
 #endif
 
-#ifndef DISABLE_SIMD
+#ifndef DISABLE_SIMD_ENCODE
 # ifdef __AVX__
 #  define _ENABLE_AVX
 # endif
@@ -1524,7 +1588,7 @@ int main(void)
 }
 #endif // TEST_ENCODE
 
-#undef DISABLE_SIMD
+#undef DISABLE_SIMD_ENCODE
 #undef _ENABLE_AVX
 #undef _ENABLE_SSE4_1
 
@@ -7259,8 +7323,8 @@ void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
 	  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]);
+	  if ( zalpha > zfac ) pdl[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
+	  if ( zbeta  > zfac ) pdr[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
 	}
       else
 	{
@@ -8020,8 +8084,8 @@ void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
 	  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]);
+	  if ( zalpha > zfac ) pdl[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
+	  if ( zbeta  > zfac ) pdr[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
 	}
       else
 	{
@@ -9282,11 +9346,6 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 {
   /* int imisng = 0; */
   int  ReducedGrid = FALSE, VertCoorTab = FALSE;
-  int  locnv = 0, locnl;
-  int  jlenl;
-  int iexp, imant;
-  int ipvpl, ipl;
-  int gdsLen = 0;
 #if defined (VECTORCODE)
   unsigned char *igrib;
   GRIBPACK *lgrib = NULL;
@@ -9297,9 +9356,9 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 
   memset(isec2, 0, 22*sizeof(int));
 
-  gdsLen = GDS_Len;
+  int gdsLen = GDS_Len;
 
-  ipvpl = GDS_PVPL;
+  int ipvpl = GDS_PVPL;
   if ( ipvpl == 0 ) ipvpl = 0xFF;
 
   if ( ipvpl != 0xFF )
@@ -9307,7 +9366,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
       if ( GDS_NV != 0 )
 	{ /* we have vct */
 	  VertCoorTab = TRUE;
-	  ipl =  4*GDS_NV + ipvpl - 1;
+	  int ipl =  4*GDS_NV + ipvpl - 1;
 	  if ( ipl < gdsLen )
 	    {
 	      ReducedGrid = TRUE;
@@ -9323,14 +9382,13 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
  
   if ( ISEC0_GRIB_Version == 0 )
     {
-      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
-      else                   VertCoorTab = FALSE;
+      VertCoorTab = (gdsLen - 32) > 0;
     }
   
   if ( ReducedGrid )
     {
-      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
-      jlenl = (gdsLen - locnl)  >> 1;
+      int locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
+      int jlenl = (gdsLen - locnl)  >> 1;
       if ( jlenl == GDS_NumLat )
 	{
 	  *numGridVals = 0;
@@ -9469,6 +9527,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 
   if ( VertCoorTab == TRUE )
     {
+      int locnv;
       if ( ISEC0_GRIB_Version  == 0 )
 	{
 	  locnv = 32;
@@ -9487,10 +9546,10 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
       if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
       for ( int 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]);
+	  int iexp   = (lgrib[4*i  ]);
+	  int imant  =(((lgrib[4*i+1]) << 16) +
+                       ((lgrib[4*i+2]) <<  8) +
+                       ( lgrib[4*i+3]));
 	  fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
 	}
 
@@ -9498,10 +9557,10 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 #else
       for ( int 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]);
+	  int iexp   = (gds[locnv+4*i  ]);
+	  int imant  =(((gds[locnv+4*i+1]) << 16) +
+                       ((gds[locnv+4*i+2]) <<  8) +
+                       ( gds[locnv+4*i+3]));
 	  fsec2[10+i] = (T)decfp2(iexp,imant);
 	}
 #endif
@@ -9601,7 +9660,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
 
   if ( ! (dfunc == 'J') && imiss == 0 )
     {
-      fmin = BDS_RefValue;
+      fmin = (T)BDS_RefValue;
       zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
     }
 
@@ -10203,11 +10262,6 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 {
   /* int imisng = 0; */
   int  ReducedGrid = FALSE, VertCoorTab = FALSE;
-  int  locnv = 0, locnl;
-  int  jlenl;
-  int iexp, imant;
-  int ipvpl, ipl;
-  int gdsLen = 0;
 #if defined (VECTORCODE)
   unsigned char *igrib;
   GRIBPACK *lgrib = NULL;
@@ -10218,9 +10272,9 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 
   memset(isec2, 0, 22*sizeof(int));
 
-  gdsLen = GDS_Len;
+  int gdsLen = GDS_Len;
 
-  ipvpl = GDS_PVPL;
+  int ipvpl = GDS_PVPL;
   if ( ipvpl == 0 ) ipvpl = 0xFF;
 
   if ( ipvpl != 0xFF )
@@ -10228,7 +10282,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
       if ( GDS_NV != 0 )
 	{ /* we have vct */
 	  VertCoorTab = TRUE;
-	  ipl =  4*GDS_NV + ipvpl - 1;
+	  int ipl =  4*GDS_NV + ipvpl - 1;
 	  if ( ipl < gdsLen )
 	    {
 	      ReducedGrid = TRUE;
@@ -10244,14 +10298,13 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
  
   if ( ISEC0_GRIB_Version == 0 )
     {
-      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
-      else                   VertCoorTab = FALSE;
+      VertCoorTab = (gdsLen - 32) > 0;
     }
   
   if ( ReducedGrid )
     {
-      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
-      jlenl = (gdsLen - locnl)  >> 1;
+      int locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
+      int jlenl = (gdsLen - locnl)  >> 1;
       if ( jlenl == GDS_NumLat )
 	{
 	  *numGridVals = 0;
@@ -10390,6 +10443,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 
   if ( VertCoorTab == TRUE )
     {
+      int locnv;
       if ( ISEC0_GRIB_Version  == 0 )
 	{
 	  locnv = 32;
@@ -10408,10 +10462,10 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
       if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
       for ( int 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]);
+	  int iexp   = (lgrib[4*i  ]);
+	  int imant  =(((lgrib[4*i+1]) << 16) +
+                       ((lgrib[4*i+2]) <<  8) +
+                       ( lgrib[4*i+3]));
 	  fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
 	}
 
@@ -10419,10 +10473,10 @@ int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2,
 #else
       for ( int 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]);
+	  int iexp   = (gds[locnv+4*i  ]);
+	  int imant  =(((gds[locnv+4*i+1]) << 16) +
+                       ((gds[locnv+4*i+2]) <<  8) +
+                       ( gds[locnv+4*i+3]));
 	  fsec2[10+i] = (T)decfp2(iexp,imant);
 	}
 #endif
@@ -10522,7 +10576,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
 
   if ( ! (dfunc == 'J') && imiss == 0 )
     {
-      fmin = BDS_RefValue;
+      fmin = (T)BDS_RefValue;
       zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
     }
 
@@ -11450,7 +11504,6 @@ void encodePDS(GRIBPACK *lpds, long pdsLen, int *isec1)
     }
 }
 
-int  BitsPerInt = (int) (sizeof(int) * 8);
 
 
 
@@ -12777,7 +12830,6 @@ void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4,
   *datasize = fsec4size;
 }
 
-
 /* 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,
@@ -12792,20 +12844,17 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
   int ival;
   long PackStart = 0, Flag = 0;
   int binscale = 0;
-  int nbpv;
   int bds_head = 11;
   int bds_ext = 0;
   /* ibits = BitsPerInt; */
   int exponent, mantissa;
-  int lspherc = FALSE, lcomplex = FALSE;
+  int lspherc = FALSE;
   int isubset = 0, itemp = 0, itrunc = 0;
   T factor = 1, fmin, fmax;
-  double zref;
-  double range;
-  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
-                                /*        of floating point numbers - needed   */
-		                /*        on some platforms (eg vpp700, linux) */
-  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
+  const double jpepsln = 1.0e-12; /* -----> tolerance used to check equality     */
+                                  /*        of floating point numbers - needed   */
+		                  /*        on some platforms (eg vpp700, linux) */
+  extern int CGRIBEX_Const;       /* 1: Don't pack constant fields on regular grids */
 
   if ( isec2 )
     {
@@ -12828,8 +12877,8 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   /* Complex packing supported for spherical harmonics. */
 
-  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
-             ( lspherc && isec2 && ( isec2[5] == 2 ) );
+  int lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
+                 ( lspherc && isec2 && ( isec2[5] == 2 ) );
 
   /* Check input specification is consistent */
 
@@ -12887,7 +12936,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   *datstart = bds_head + bds_ext;
 
-  nbpv = numBits = ISEC4_NumBits;
+  int nbpv = numBits = ISEC4_NumBits;
 
   if ( lspherc && lcomplex )
     {
@@ -12902,7 +12951,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
 
-  zref = (double)fmin;
+  double zref = (double)fmin;
 
 
   if ( CGRIBEX_Const && !lspherc )
@@ -12930,7 +12979,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
     Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
     as a guideline).           
   */
-  range = fabs(fmax - fmin);
+  double range = fabs(fmax - fmin);
 
   if ( fabs(fmin) < FLT_MIN ) fmin = 0;
   /*
@@ -12954,7 +13003,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
     {
       double rangec = range + jpepsln,
         p2 = 2.0;
-      long jloop = 1;
+      int jloop = 1;
       while ( jloop < 128 && p2 <= rangec )
         {
           p2 *= 2.0;
@@ -12972,7 +13021,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
   else
     {
       double rangec = range - jpepsln, p05 = 0.5;
-      long jloop = 1;
+      int jloop = 1;
       while ( jloop < 127 && p05 >= rangec )
 	{
           p05 *= 0.5;
@@ -12994,12 +13043,9 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   if ( binscale != 0 )
     {
-      if ( binscale < 0 )
-        while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
-      else
-        while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale--;
+      while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
 
-      factor = intpow2(-binscale);
+      factor = (T)intpow2(-binscale);
     }
 
   ref2ibm(&zref, BitsPerInt);
@@ -13393,7 +13439,6 @@ void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4,
   *datasize = fsec4size;
 }
 
-
 /* 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,
@@ -13408,20 +13453,17 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
   int ival;
   long PackStart = 0, Flag = 0;
   int binscale = 0;
-  int nbpv;
   int bds_head = 11;
   int bds_ext = 0;
   /* ibits = BitsPerInt; */
   int exponent, mantissa;
-  int lspherc = FALSE, lcomplex = FALSE;
+  int lspherc = FALSE;
   int isubset = 0, itemp = 0, itrunc = 0;
   T factor = 1, fmin, fmax;
-  double zref;
-  double range;
-  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
-                                /*        of floating point numbers - needed   */
-		                /*        on some platforms (eg vpp700, linux) */
-  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
+  const double jpepsln = 1.0e-12; /* -----> tolerance used to check equality     */
+                                  /*        of floating point numbers - needed   */
+		                  /*        on some platforms (eg vpp700, linux) */
+  extern int CGRIBEX_Const;       /* 1: Don't pack constant fields on regular grids */
 
   if ( isec2 )
     {
@@ -13444,8 +13486,8 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   /* Complex packing supported for spherical harmonics. */
 
-  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
-             ( lspherc && isec2 && ( isec2[5] == 2 ) );
+  int lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
+                 ( lspherc && isec2 && ( isec2[5] == 2 ) );
 
   /* Check input specification is consistent */
 
@@ -13503,7 +13545,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   *datstart = bds_head + bds_ext;
 
-  nbpv = numBits = ISEC4_NumBits;
+  int nbpv = numBits = ISEC4_NumBits;
 
   if ( lspherc && lcomplex )
     {
@@ -13518,7 +13560,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
 
-  zref = (double)fmin;
+  double zref = (double)fmin;
 
 
   if ( CGRIBEX_Const && !lspherc )
@@ -13546,7 +13588,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
     Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
     as a guideline).           
   */
-  range = fabs(fmax - fmin);
+  double range = fabs(fmax - fmin);
 
   if ( fabs(fmin) < FLT_MIN ) fmin = 0;
   /*
@@ -13570,7 +13612,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
     {
       double rangec = range + jpepsln,
         p2 = 2.0;
-      long jloop = 1;
+      int jloop = 1;
       while ( jloop < 128 && p2 <= rangec )
         {
           p2 *= 2.0;
@@ -13588,7 +13630,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
   else
     {
       double rangec = range - jpepsln, p05 = 0.5;
-      long jloop = 1;
+      int jloop = 1;
       while ( jloop < 127 && p05 >= rangec )
 	{
           p05 *= 0.5;
@@ -13610,12 +13652,9 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
 
   if ( binscale != 0 )
     {
-      if ( binscale < 0 )
-        while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
-      else
-        while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale--;
+      while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
 
-      factor = intpow2(-binscale);
+      factor = (T)intpow2(-binscale);
     }
 
   ref2ibm(&zref, BitsPerInt);
@@ -13784,7 +13823,7 @@ 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.7.4" " of ""Feb 19 2016"" ""11:03:41";
+static const char grb_libvers[] = "1.7.5" " of ""Jun  3 2016"" ""14:44:00";
 const char *
 cgribexLibraryVersion(void)
 {
diff --git a/libcdi/src/config.h.in b/libcdi/src/config.h.in
index f7ceef6..8f6932d 100644
--- a/libcdi/src/config.h.in
+++ b/libcdi/src/config.h.in
@@ -79,8 +79,8 @@
 /* Define to 1 if you have the `grib_get_length' function. */
 #undef HAVE_GRIB_GET_LENGTH
 
-/* Define to 1 if you have the <hdf5.h> header file. */
-#undef HAVE_HDF5_H
+/* Define to 1 for H5get_libversion support */
+#undef HAVE_H5GET_LIBVERSION
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
@@ -100,9 +100,6 @@
 /* GRIB_API library is present if defined to 1 */
 #undef HAVE_LIBGRIB_API
 
-/* Define to 1 for HDF5 support */
-#undef HAVE_LIBHDF5
-
 /* Define to 1 for IEG interface */
 #undef HAVE_LIBIEG
 
@@ -118,10 +115,10 @@
 /* Define to 1 if you have the `malloc' library (-lmalloc). */
 #undef HAVE_LIBMALLOC
 
-/* Define to 1 for NETCDF OpenDAP */
+/* Define to 1 for NetCDF OpenDAP */
 #undef HAVE_LIBNC_DAP
 
-/* Define to 1 for NETCDF support */
+/* Define to 1 for NetCDF support */
 #undef HAVE_LIBNETCDF
 
 /* Define to 1 for JPEG compression for GRIB2 */
@@ -136,9 +133,6 @@
 /* Define to 1 for SZIP support */
 #undef HAVE_LIBSZ
 
-/* Define 1 for ZLIB support */
-#undef HAVE_LIBZ
-
 /* Define to 1 if you have the `mallinfo' function. */
 #undef HAVE_MALLINFO
 
@@ -151,10 +145,16 @@
 /* Define to 1 if you have a working `mmap' system call. */
 #undef HAVE_MMAP
 
-/* Define to 1 for NETCDF2 support */
+/* Define to 1 for NetCDF4/HDF5 support */
+#undef HAVE_NC4HDF5
+
+/* Define to 1 for NetCDF4/HDF5 threadsafe support */
+#undef HAVE_NC4HDF5_THREADSAFE
+
+/* Define to 1 for NetCDF2 support */
 #undef HAVE_NETCDF2
 
-/* Define to 1 for NETCDF4 support */
+/* Define to 1 for NetCDF4 support */
 #undef HAVE_NETCDF4
 
 /* Define to 1 if you have the <netcdf.h> header file. */
@@ -223,9 +223,6 @@
 /* yaxt library is available */
 #undef HAVE_YAXT
 
-/* Define to 1 if you have the <zlib.h> header file. */
-#undef HAVE_ZLIB_H
-
 /* Host name */
 #undef HOST_NAME
 
diff --git a/libcdi/src/dtypes.h b/libcdi/src/dtypes.h
index f69ea49..ca849ce 100644
--- a/libcdi/src/dtypes.h
+++ b/libcdi/src/dtypes.h
@@ -1,5 +1,5 @@
-#ifndef _DTYPES_H
-#define _DTYPES_H
+#ifndef DTYPES_H
+#define DTYPES_H
 
 #include <stdio.h>
 #include <limits.h>
@@ -45,7 +45,7 @@
 #define  UINT32   unsigned INT32
 #define  UINT64   unsigned INT64
 
-#endif  /* _DTYPES_H */
+#endif  /* DTYPES_H */
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/libcdi/src/grb_write.c b/libcdi/src/grb_write.c
index dd8cc9f..f47eb68 100644
--- a/libcdi/src/grb_write.c
+++ b/libcdi/src/grb_write.c
@@ -246,7 +246,7 @@ void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data
 }
 
 
-void 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 varID   = streamptr->record->varID;
   int levelID = streamptr->record->levelID;
@@ -254,4 +254,5 @@ void grb_write_record(stream_t * streamptr, int memtype, const void *data, int n
   grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
 }
 
+
 #endif
diff --git a/libcdi/src/gribapi_utilities.c b/libcdi/src/gribapi_utilities.c
index 90a2a98..9bdcaf6 100644
--- a/libcdi/src/gribapi_utilities.c
+++ b/libcdi/src/gribapi_utilities.c
@@ -471,27 +471,24 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     case GRID_LONLAT:
     case GRID_GAUSSIAN:
       {
-        long lpar;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &lpar);
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        int nlon = (int)lpar;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &lpar);
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        int nlat = (int)lpar;
+        long nlon, nlat;
+        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &nlon);
+        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &nlat);
 
         if ( gridtype == GRID_GAUSSIAN )
           {
+            long lpar;
             FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar);
             grid->np = (int)lpar;
           }
 
         if ( numberOfPoints != nlon*nlat )
-          Error("numberOfPoints (%ld) and gridSize (%d) differ!", numberOfPoints, nlon*nlat);
+          Error("numberOfPoints (%ld) and gridSize (%ld) differ!", numberOfPoints, nlon*nlat);
 
         /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
         grid->size  = (int)numberOfPoints;
-        grid->xsize = nlon;
-        grid->ysize = nlat;
+        grid->xsize = (int)nlon;
+        grid->ysize = (int)nlat;
         grid->xinc  = 0;
         grid->yinc  = 0;
         grid->xdef  = 0;
@@ -499,13 +496,16 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
-        if ( gridtype == GRID_LONLAT )
+        if ( nlon > 1 )
+          FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
+        if ( gridtype == GRID_LONLAT && nlat > 1 )
           FAIL_ON_GRIB_ERROR(grib_get_double, gh, "jDirectionIncrementInDegrees", &grid->yinc);
 
         if ( grid->xinc < -999 || grid->xinc > 999 ) grid->xinc = 0;
         if ( grid->yinc < -999 || grid->yinc > 999 ) grid->yinc = 0;
 
+        if ( grid->yinc > 0 && grid->yfirst > grid->ylast ) grid->yinc = -grid->yinc;
+
         /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
           {
             if ( grid->xsize > 1 )
@@ -544,9 +544,6 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
       }
     case GRID_GAUSSIAN_REDUCED:
       {
-        size_t dummy;
-        long *pl;
-
         long lpar;
         FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar);
         /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
@@ -559,12 +556,13 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
         grid->size   = (int)numberOfPoints;
 
+        grid->nrowlon = nlat;
         grid->rowlon = (int *) Malloc((size_t)nlat * sizeof (int));
-        pl          = (long *) Malloc((size_t)nlat * sizeof (long));
-        dummy       = (size_t)nlat;
+        long *pl     = (long *) Malloc((size_t)nlat * sizeof (long));
+        size_t dummy = (size_t)nlat;
         FAIL_ON_GRIB_ERROR(grib_get_long_array, gh, "pl", pl, &dummy);
         /* FIXME: assert(pl[i] >= INT_MIN && pl[i] <= INT_MIN) */
-        for (int i = 0; i < nlat; ++i ) grid->rowlon[i] = (int)pl[i];
+        for ( int i = 0; i < nlat; ++i ) grid->rowlon[i] = (int)pl[i];
         Free(pl);
 
         grid->ysize  = nlat;
@@ -575,9 +573,9 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst);
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
 
-        if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0;
+        // FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
+        // if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0;
 
         /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
           {
diff --git a/libcdi/src/grid.c b/libcdi/src/grid.c
index 64cc1df..9a68135 100644
--- a/libcdi/src/grid.c
+++ b/libcdi/src/grid.c
@@ -91,79 +91,82 @@ grid_t *gridID2Ptr(int gridID)
 
 void grid_init(grid_t *gridptr)
 {
-  gridptr->self         = CDI_UNDEFID;
-  gridptr->type         = CDI_UNDEFID;
-  gridptr->proj         = CDI_UNDEFID;
-  gridptr->mask         = NULL;
-  gridptr->mask_gme     = NULL;
-  gridptr->xvals        = NULL;
-  gridptr->yvals        = NULL;
-  gridptr->area         = NULL;
-  gridptr->xbounds      = NULL;
-  gridptr->ybounds      = NULL;
-  gridptr->rowlon       = NULL;
-  gridptr->nrowlon      = 0;
-  gridptr->xfirst       = 0.0;
-  gridptr->xlast        = 0.0;
-  gridptr->xinc         = 0.0;
-  gridptr->yfirst       = 0.0;
-  gridptr->ylast        = 0.0;
-  gridptr->yinc         = 0.0;
+  gridptr->self          = CDI_UNDEFID;
+  gridptr->type          = CDI_UNDEFID;
+  gridptr->proj          = CDI_UNDEFID;
+  gridptr->mask          = NULL;
+  gridptr->mask_gme      = NULL;
+  gridptr->xvals         = NULL;
+  gridptr->yvals         = NULL;
+  gridptr->area          = NULL;
+  gridptr->xbounds       = NULL;
+  gridptr->ybounds       = NULL;
+  gridptr->rowlon        = NULL;
+  gridptr->nrowlon       = 0;
+  gridptr->xfirst        = 0.0;
+  gridptr->xlast         = 0.0;
+  gridptr->xinc          = 0.0;
+  gridptr->yfirst        = 0.0;
+  gridptr->ylast         = 0.0;
+  gridptr->yinc          = 0.0;
   gridptr->lcc_originLon = 0.0;
   gridptr->lcc_originLat = 0.0;
-  gridptr->lcc_lonParY  = 0.0;
-  gridptr->lcc_lat1     = 0.0;
-  gridptr->lcc_lat2     = 0.0;
-  gridptr->lcc_xinc     = 0.0;
-  gridptr->lcc_yinc     = 0.0;
-  gridptr->lcc_projflag = 0;
-  gridptr->lcc_scanflag = 0;
-  gridptr->lcc_defined  = FALSE;
-  gridptr->lcc2_lon_0   = 0.0;
-  gridptr->lcc2_lat_0   = 0.0;
-  gridptr->lcc2_lat_1   = 0.0;
-  gridptr->lcc2_lat_2   = 0.0;
-  gridptr->lcc2_a       = 0.0;
-  gridptr->lcc2_defined = FALSE;
-  gridptr->laea_lon_0   = 0.0;
-  gridptr->laea_lat_0   = 0.0;
-  gridptr->laea_a       = 0.0;
-  gridptr->laea_defined = FALSE;
-  gridptr->trunc        = 0;
-  gridptr->nvertex      = 0;
-  gridptr->nd           = 0;
-  gridptr->ni           = 0;
-  gridptr->ni2          = 0;
-  gridptr->ni3          = 0;
-  gridptr->number       = 0;
-  gridptr->position     = 0;
-  gridptr->reference    = NULL;
-  gridptr->prec         = 0;
-  gridptr->size         = 0;
-  gridptr->xsize        = 0;
-  gridptr->ysize        = 0;
-  gridptr->np           = 0;
-  gridptr->xdef         = 0;
-  gridptr->ydef         = 0;
-  gridptr->isCyclic     = CDI_UNDEFID;
-  gridptr->isRotated    = FALSE;
-  gridptr->xpole        = 0.0;
-  gridptr->ypole        = 0.0;
-  gridptr->angle        = 0.0;
-  gridptr->lcomplex     = 0;
-  gridptr->hasdims      = TRUE;
-  gridptr->xname[0]     = 0;
-  gridptr->yname[0]     = 0;
-  gridptr->xlongname[0] = 0;
-  gridptr->ylongname[0] = 0;
-  gridptr->xunits[0]    = 0;
-  gridptr->yunits[0]    = 0;
-  gridptr->xstdname  = NULL;
-  gridptr->ystdname  = NULL;
+  gridptr->lcc_lonParY   = 0.0;
+  gridptr->lcc_lat1      = 0.0;
+  gridptr->lcc_lat2      = 0.0;
+  gridptr->lcc_xinc      = 0.0;
+  gridptr->lcc_yinc      = 0.0;
+  gridptr->lcc_projflag  = 0;
+  gridptr->lcc_scanflag  = 0;
+  gridptr->lcc_defined   = FALSE;
+  gridptr->lcc2_lon_0    = 0.0;
+  gridptr->lcc2_lat_0    = 0.0;
+  gridptr->lcc2_lat_1    = 0.0;
+  gridptr->lcc2_lat_2    = 0.0;
+  gridptr->lcc2_a        = 0.0;
+  gridptr->lcc2_defined  = FALSE;
+  gridptr->laea_lon_0    = 0.0;
+  gridptr->laea_lat_0    = 0.0;
+  gridptr->laea_a        = 0.0;
+  gridptr->laea_defined  = FALSE;
+  gridptr->trunc         = 0;
+  gridptr->nvertex       = 0;
+  gridptr->nd            = 0;
+  gridptr->ni            = 0;
+  gridptr->ni2           = 0;
+  gridptr->ni3           = 0;
+  gridptr->number        = 0;
+  gridptr->position      = 0;
+  gridptr->reference     = NULL;
+  gridptr->prec          = 0;
+  gridptr->size          = 0;
+  gridptr->xsize         = 0;
+  gridptr->ysize         = 0;
+  gridptr->np            = 0;
+  gridptr->xdef          = 0;
+  gridptr->ydef          = 0;
+  gridptr->isCyclic      = CDI_UNDEFID;
+  gridptr->isRotated     = FALSE;
+  gridptr->xpole         = 0.0;
+  gridptr->ypole         = 0.0;
+  gridptr->angle         = 0.0;
+  gridptr->lcomplex      = 0;
+  gridptr->hasdims       = TRUE;
+  gridptr->xdimname[0]   = 0;
+  gridptr->ydimname[0]   = 0;
+  gridptr->vdimname[0]   = 0;
+  gridptr->xname[0]      = 0;
+  gridptr->yname[0]      = 0;
+  gridptr->xlongname[0]  = 0;
+  gridptr->ylongname[0]  = 0;
+  gridptr->xunits[0]     = 0;
+  gridptr->yunits[0]     = 0;
+  gridptr->xstdname      = NULL;
+  gridptr->ystdname      = NULL;
   memset(gridptr->uuid, 0, CDI_UUID_SIZE);
-  gridptr->name         = NULL;
-  gridptr->vtable       = &cdiGridVtable;
-  gridptr->extraData    = NULL;
+  gridptr->name          = NULL;
+  gridptr->vtable        = &cdiGridVtable;
+  gridptr->extraData     = NULL;
 }
 
 
@@ -201,16 +204,15 @@ gridNewEntry(cdiResH resH)
 }
 
 static
-void gridInit (void)
+void gridInit(void)
 {
   static int gridInitialized = 0;
-  char *env;
 
   if ( gridInitialized ) return;
 
   gridInitialized = 1;
 
-  env = getenv("GRID_DEBUG");
+  const char *env = getenv("GRID_DEBUG");
   if ( env ) GRID_Debug = atoi(env);
 }
 
@@ -238,52 +240,32 @@ unsigned cdiGridCount(void)
   return reshCountType(&gridOps);
 }
 
-static inline void
-gridSetXname(grid_t *gridptr, const char *xname)
-{
-  strncpy(gridptr->xname, xname, CDI_MAX_NAME);
-  gridptr->xname[CDI_MAX_NAME - 1] = 0;
-}
-
-static inline void
-gridSetXlongname(grid_t *gridptr, const char *xlongname)
-{
-  strncpy(gridptr->xlongname, xlongname, CDI_MAX_NAME);
-  gridptr->xlongname[CDI_MAX_NAME - 1] = 0;
-}
-
-static inline void
-gridSetXunits(grid_t *gridptr, const char *xunits)
-{
-  strncpy(gridptr->xunits, xunits, CDI_MAX_NAME);
-  gridptr->xunits[CDI_MAX_NAME - 1] = 0;
-}
-
-static inline void
-gridSetYname(grid_t *gridptr, const char *yname)
+static inline
+void gridSetString(char *gridstrname, const char *name, size_t len)
 {
-  strncpy(gridptr->yname, yname, CDI_MAX_NAME);
-  gridptr->yname[CDI_MAX_NAME - 1] = 0;
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(gridstrname, name, len);
+  gridstrname[len - 1] = 0;
 }
 
-static inline void
-gridSetYlongname(grid_t *gridptr, const char *ylongname)
+static inline
+void gridGetString(char *name, const char *gridstrname, size_t len)
 {
-  strncpy(gridptr->ylongname, ylongname, CDI_MAX_NAME);
-  gridptr->ylongname[CDI_MAX_NAME - 1] = 0;
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(name, gridstrname, len);
+  name[len - 1] = 0;
 }
 
 static inline void
-gridSetYunits(grid_t *gridptr, const char *yunits)
+gridSetName(char *gridstrname, const char *name)
 {
-  strncpy(gridptr->yunits, yunits, CDI_MAX_NAME);
-  gridptr->yunits[CDI_MAX_NAME - 1] = 0;
+  strncpy(gridstrname, name, CDI_MAX_NAME);
+  gridstrname[CDI_MAX_NAME - 1] = 0;
 }
 
 void
 cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
 {
-
   gridptr->type = gridtype;
   gridptr->size = size;
 
@@ -299,16 +281,16 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
       {
         if ( gridtype == GRID_TRAJECTORY )
           {
-            gridSetXname(gridptr, "tlon");
-            gridSetYname(gridptr, "tlat");
+            if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "tlon");
+            if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "tlat");
           }
         else
           {
-            gridSetXname(gridptr, "lon");
-            gridSetYname(gridptr, "lat");
+            if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon");
+            if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat");
           }
-        gridSetXlongname(gridptr, "longitude");
-        gridSetYlongname(gridptr, "latitude");
+        gridSetName(gridptr->xlongname, "longitude");
+        gridSetName(gridptr->ylongname, "latitude");
 
         /*
         if ( gridtype == GRID_CURVILINEAR )
@@ -323,8 +305,8 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
           {
             gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
             gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
-            gridSetXunits(gridptr, "degrees_east");
-            gridSetYunits(gridptr, "degrees_north");
+            gridSetName(gridptr->xunits, "degrees_east");
+            gridSetName(gridptr->yunits, "degrees_north");
           }
 
         break;
@@ -334,20 +316,20 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
       /* Fall through */
     case GRID_GME:
       {
-        gridSetXname(gridptr, "lon");
-        gridSetYname(gridptr, "lat");
+        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon");
+        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat");
         gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
         gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
-        gridSetXunits(gridptr, "degrees_east");
-        gridSetYunits(gridptr, "degrees_north");
+        gridSetName(gridptr->xunits, "degrees_east");
+        gridSetName(gridptr->yunits, "degrees_north");
         break;
       }
     case GRID_GENERIC:
       {
 
         /* gridptr->xsize = size; */
-        gridSetXname(gridptr, "x");
-        gridSetYname(gridptr, "y");
+        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x");
+        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y");
         /*
         strcpy(gridptr->xstdname, "grid_longitude");
         strcpy(gridptr->ystdname, "grid_latitude");
@@ -362,16 +344,15 @@ cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
     case GRID_SINUSOIDAL:
     case GRID_LAEA:
       {
-        gridSetXname(gridptr, "x");
-        gridSetYname(gridptr, "y");
+        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x");
+        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y");
         gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0];
         gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1];
-        gridSetXunits(gridptr, "m");
-        gridSetYunits(gridptr, "m");
+        gridSetName(gridptr->xunits, "m");
+        gridSetName(gridptr->yunits, "m");
         break;
       }
     }
-
 }
 
 
@@ -516,7 +497,7 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
     @Item  gridtype  The type of the grid, one of the set of predefined CDI grid types.
                      The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
                      @func{GRID_LONLAT}, @func{GRID_LCC}, @func{GRID_SPECTRAL},
-                     @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED} and.
+                     @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
     @Item  size      Number of gridpoints.
 
 @Description
@@ -564,7 +545,7 @@ int gridCreate(int gridtype, int size)
 
   cdiGridTypeInit(gridptr, gridtype, size);
 
-  return (gridID);
+  return gridID;
 }
 
 static
@@ -610,7 +591,7 @@ const char *gridNamePtr(int gridtype)
 
   const char *name = gridtype >= 0 && gridtype < size ? Grids[gridtype] : Grids[GRID_GENERIC];
 
-  return (name);
+  return name;
 }
 
 
@@ -619,6 +600,98 @@ void gridName(int gridtype, char *gridname)
   strcpy(gridname, gridNamePtr(gridtype));
 }
 
+static
+char *grid_key_to_string(grid_t *gridptr, int key)
+{
+  char *gridstring = NULL;
+
+  switch (key)
+    {
+    case CDI_GRID_XDIMNAME: gridstring = gridptr->xdimname; break;
+    case CDI_GRID_YDIMNAME: gridstring = gridptr->ydimname; break;
+    case CDI_GRID_VDIMNAME: gridstring = gridptr->vdimname; break;
+    }
+
+  return gridstring;
+}
+
+/*
+ at Function  cdiGridDefString
+ at Title     Define a CDI grid string value from a key
+
+ at Prototype int cdiGridDefString(int gridID, int key, int size, const char *mesg)
+ at Parameter
+    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
+    @Item  key      The key to be searched
+    @Item  size     The allocated length of the string on input
+    @Item  mesg     The address of a string where the data will be read
+
+ at Description
+The function @func{cdiGridDefString} defines a CDI grid string value from a key.
+
+ at Result
+ at func{cdiGridDefString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiGridDefString(int gridID, int key, int size, const char *mesg)
+{
+  if ( size < 1 || mesg == NULL || *mesg == 0 ) return -1;
+
+  grid_t *gridptr = gridID2Ptr(gridID);
+
+  char *gridstring = grid_key_to_string(gridptr, key);
+  if ( gridstring == NULL )
+    {
+      Warning("CDI grid string key %d not supported!", key);
+      return -1;
+    }
+
+  gridSetString(gridstring, mesg, (size_t)size);
+  gridMark4Update(gridID);
+
+  return 0;
+}
+
+/*
+ at Function  cdiGridInqString
+ at Title     Get a CDI grid string value from a key
+
+ at Prototype int cdiGridInqString(int gridID, int key, int size, char *mesg)
+ at Parameter
+    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
+    @Item  key      The key to be searched.
+    @Item  size     The allocated length of the string on input.
+    @Item  mesg     The address of a string where the data will be retrieved.
+                    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}.
+
+ at Description
+The function @func{cdiGridInqString} return a CDI grid string value from a key.
+
+ at Result
+ at func{cdiGridInqString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiGridInqString(int gridID, int key, int size, char *mesg)
+{
+  if ( size < 1 || mesg == NULL ) return -1;
+
+  grid_t *gridptr = gridID2Ptr(gridID);
+  const char *gridstring = grid_key_to_string(gridptr, key);
+  if ( gridstring == NULL)
+    {
+      Warning("CDI grid string key %d not supported!", key);
+      return -1;
+    }
+
+  gridGetString(mesg, gridstring, (size_t)size);
+
+  return 0;
+}
+
 /*
 @Function  gridDefXname
 @Title     Define the name of a X-axis
@@ -638,12 +711,11 @@ void gridDefXname(int gridID, const char *xname)
   if ( xname && *xname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetXname(gridptr, xname);
+      gridSetName(gridptr->xname, xname);
       gridMark4Update(gridID);
     }
 }
 
-
 /*
 @Function  gridDefXlongname
 @Title     Define the longname of a X-axis
@@ -663,7 +735,7 @@ void gridDefXlongname(int gridID, const char *xlongname)
   if ( xlongname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetXlongname(gridptr, xlongname);
+      gridSetName(gridptr->xlongname, xlongname);
       gridMark4Update(gridID);
     }
 }
@@ -687,7 +759,7 @@ void gridDefXunits(int gridID, const char *xunits)
   if ( xunits )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetXunits(gridptr, xunits);
+      gridSetName(gridptr->xunits, xunits);
       gridMark4Update(gridID);
     }
 }
@@ -711,7 +783,7 @@ void gridDefYname(int gridID, const char *yname)
   if ( yname && *yname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetYname(gridptr, yname);
+      gridSetName(gridptr->yname, yname);
       gridMark4Update(gridID);
     }
 }
@@ -735,7 +807,7 @@ void gridDefYlongname(int gridID, const char *ylongname)
   if ( ylongname )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetYlongname(gridptr, ylongname);
+      gridSetName(gridptr->ylongname, ylongname);
       gridMark4Update(gridID);
     }
 }
@@ -759,7 +831,7 @@ void gridDefYunits(int gridID, const char *yunits)
   if ( yunits )
     {
       grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetYunits(gridptr, yunits);
+      gridSetName(gridptr->yunits, yunits);
       gridMark4Update(gridID);
     }
 }
@@ -790,6 +862,12 @@ void gridInqXname(int gridID, char *xname)
   strcpy(xname, gridptr->xname);
 }
 
+const char *gridInqXnamePtr(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  return gridptr->xname;
+}
+
 /*
 @Function  gridInqXlongname
 @Title     Get the longname of a X-axis
@@ -878,6 +956,12 @@ void gridInqYname(int gridID, char *yname)
   strcpy(yname, gridptr->yname);
 }
 
+const char *gridInqYnamePtr(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  return gridptr->yname;
+}
+
 /*
 @Function  gridInqYlongname
 @Title     Get the longname of a Y-axis
@@ -963,7 +1047,7 @@ int gridInqType(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->type);
+  return gridptr->type;
 }
 
 
@@ -989,12 +1073,10 @@ int gridInqSize(int gridID)
 
   int size = gridptr->size;
 
-  if ( ! size )
+  if ( size == 0 )
     {
-      int xsize, ysize;
-
-      xsize = gridptr->xsize;
-      ysize = gridptr->ysize;
+      int xsize = gridptr->xsize;
+      int ysize = gridptr->ysize;
 
       if ( ysize )
         size = xsize * ysize;
@@ -1004,7 +1086,7 @@ int gridInqSize(int gridID)
       gridptr->size = size;
     }
 
-  return (size);
+  return size;
 }
 
 static
@@ -1017,7 +1099,7 @@ int nsp2trunc(int nsp)
   /*         y = -p/2 +- sqrt((p/2)^2 - q)   */
   /*         p = 3 and q = - (x-2)           */
   int trunc = (int) (sqrt(nsp*4 + 1.) - 3) / 2;
-  return (trunc);
+  return trunc;
 }
 
 
@@ -1035,7 +1117,7 @@ int gridInqTrunc(int gridID)
       */
     }
 
-  return (gridptr->trunc);
+  return gridptr->trunc;
 }
 
 
@@ -1043,7 +1125,7 @@ void gridDefTrunc(int gridID, int trunc)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->trunc != trunc)
+  if ( gridptr->trunc != trunc )
     {
       gridMark4Update(gridID);
       gridptr->trunc = trunc;
@@ -1076,7 +1158,7 @@ void gridDefXsize(int gridID, int xsize)
   if ( gridType == GRID_UNSTRUCTURED && xsize != gridSize )
     Error("xsize %d must be equal to gridsize %d for gridtype: UNSTRUCTURED", xsize, gridSize);
 
-  if (gridptr->xsize != xsize)
+  if ( gridptr->xsize != xsize )
     {
       gridMark4Update(gridID);
       gridptr->xsize = xsize;
@@ -1105,7 +1187,7 @@ void gridDefPrec(int gridID, int prec)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->prec != prec)
+  if ( gridptr->prec != prec )
     {
       gridMark4Update(gridID);
       gridptr->prec = prec;
@@ -1126,7 +1208,7 @@ int gridInqPrec(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->prec);
+  return gridptr->prec;
 }
 
 /*
@@ -1149,7 +1231,7 @@ int gridInqXsize(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->xsize);
+  return gridptr->xsize;
 }
 
 /*
@@ -1178,7 +1260,7 @@ void gridDefYsize(int gridID, int ysize)
   if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ysize != gridSize )
     Error("ysize %d must be equal gridsize %d for gridtype: UNSTRUCTURED", ysize, gridSize);
 
-  if (gridptr->ysize != ysize)
+  if ( gridptr->ysize != ysize )
     {
       gridMark4Update(gridID);
       gridptr->ysize = ysize;
@@ -1213,7 +1295,7 @@ int gridInqYsize(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->ysize);
+  return gridptr->ysize;
 }
 
 /*
@@ -1235,7 +1317,7 @@ void gridDefNP(int gridID, int np)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->np != np)
+  if ( gridptr->np != np )
     {
       gridMark4Update(gridID);
       gridptr->np = np;
@@ -1263,7 +1345,7 @@ int gridInqNP(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->np);
+  return gridptr->np;
 }
 
 /*
@@ -1315,7 +1397,7 @@ gridInqMaskSerialGeneric(grid_t *gridptr, mask_t **internalMask,
     Warning("Size undefined for gridID = %d", gridptr->self);
 
   const mask_t *restrict mask_src = *internalMask;
-  if (mask_src)
+  if ( mask_src )
     {
       if (mask && size > 0)
         for (size_t i = 0; i < (size_t)size; ++i)
@@ -1436,6 +1518,7 @@ gridInqXValsSerial(grid_t *gridptr, double *xvals)
     }
   else
     size = 0;
+
   return (int)size;
 }
 
@@ -1697,7 +1780,7 @@ double gridInqYinc(int gridID)
         {
           yinc = yvals[1] - yvals[0];
           double abs_yinc = fabs(yinc);
-          for (size_t i = 2; i < (size_t)ysize; i++ )
+          for ( size_t i = 2; i < (size_t)ysize; i++ )
             if ( fabs(fabs(yvals[i] - yvals[i-1]) - abs_yinc) > (0.01*abs_yinc) )
               {
                 yinc = 0;
@@ -1770,7 +1853,7 @@ double gridInqYpole(int gridID)
   // Ypole -> grid_north_pole_latitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->ypole);
+  return gridptr->ypole;
 }
 
 /*
@@ -1814,7 +1897,7 @@ double gridInqAngle(int gridID)
   // Angle -> north_pole_grid_longitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->angle);
+  return gridptr->angle;
 }
 
 /*
@@ -1854,7 +1937,7 @@ int gridInqGMEnd(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->nd);
+  return gridptr->nd;
 }
 
 /*
@@ -1892,7 +1975,7 @@ int gridInqGMEni(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->ni);
+  return gridptr->ni;
 }
 
 /*
@@ -1909,7 +1992,7 @@ void gridDefGMEni(int gridID, int ni)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->ni != ni)
+  if ( gridptr->ni != ni )
     {
       gridptr->ni = ni;
       gridMark4Update(gridID);
@@ -1930,7 +2013,7 @@ int gridInqGMEni2(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->ni2);
+  return gridptr->ni2;
 }
 
 /*
@@ -1947,7 +2030,7 @@ void gridDefGMEni2(int gridID, int ni2)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->ni2 != ni2)
+  if ( gridptr->ni2 != ni2 )
     {
       gridptr->ni2 = ni2;
       gridMark4Update(gridID);
@@ -1968,14 +2051,14 @@ int gridInqGMEni3(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->ni3);
+  return gridptr->ni3;
 }
 
 void gridDefGMEni3(int gridID, int ni3)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->ni3 != ni3)
+  if ( gridptr->ni3 != ni3 )
     {
       gridptr->ni3 = ni3;
       gridMark4Update(gridID);
@@ -2062,7 +2145,7 @@ void grid_check_cyclic(grid_t *gridptr)
 
       if ( xbounds && xsize > 1 )
 	{
-          short isCyclic = TRUE;
+          bool isCyclic = true;
 	  for ( size_t j = 0; j < ysize; ++j )
 	    {
 	      size_t i1 = j*xsize,
@@ -2085,12 +2168,12 @@ void grid_check_cyclic(grid_t *gridptr)
 		    }
 		}
               /* all vertices more than 0.001 degrees apart */
-              isCyclic = FALSE;
+              isCyclic = false;
               break;
               foundCloseVertices:
               ;
 	    }
-          gridptr->isCyclic = isCyclic;
+          gridptr->isCyclic = (int) isCyclic;
 	}
     }
 }
@@ -2102,7 +2185,7 @@ int gridIsCircular(int gridID)
 
   if ( gridptr->isCyclic == CDI_UNDEFID ) grid_check_cyclic(gridptr);
 
-  return ( gridptr->isCyclic );
+  return gridptr->isCyclic;
 }
 
 
@@ -2110,13 +2193,13 @@ int gridIsRotated(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return ( gridptr->isRotated );
+  return gridptr->isRotated;
 }
 
 static
-int compareXYvals(grid_t *gridRef, grid_t *gridTest)
+bool compareXYvals(grid_t *gridRef, grid_t *gridTest)
 {
-  int differ = 0;
+  bool differ = false;
 
   int xsizeTest = gridTest->xsize, ysizeTest = gridTest->ysize;
   if ( !differ && xsizeTest > 0 && xsizeTest == gridRef->vtable->inqXVals(gridRef, NULL) )
@@ -2127,7 +2210,7 @@ int compareXYvals(grid_t *gridRef, grid_t *gridTest)
       for ( size_t i = 0; i < (size_t)xsizeTest; ++i )
 	if ( fabs(xvalsTest[i] - xvalsRef[i]) > 1.e-10 )
 	  {
-	    differ = 1;
+	    differ = true;
 	    break;
 	  }
     }
@@ -2139,19 +2222,19 @@ int compareXYvals(grid_t *gridRef, grid_t *gridTest)
       for ( size_t i = 0; i < (size_t)ysizeTest; ++i )
 	if ( fabs(yvalsTest[i] - yvalsRef[i]) > 1.e-10 )
 	  {
-	    differ = 1;
+	    differ = true;
 	    break;
 	  }
     }
 
-  return (differ);
+  return differ;
 }
 
 static
-int compareXYvals2(grid_t *gridRef, grid_t *gridTest)
+bool compareXYvals2(grid_t *gridRef, grid_t *gridTest)
 {
   int gridsize = gridTest->size;
-  int differ
+  bool differ
     = ((gridTest->xvals == NULL) ^ (gridRef->xvals == NULL))
     || ((gridTest->yvals == NULL) ^ (gridRef->yvals == NULL));
 
@@ -2172,17 +2255,17 @@ int compareXYvals2(grid_t *gridRef, grid_t *gridTest)
   return differ;
 }
 
-
-int gridCompare(int gridID, const grid_t *grid)
+static
+bool gridCompare(int gridID, const grid_t *grid)
 {
-  int differ = 1;
+  bool differ = true;
   grid_t *gridRef = gridID2Ptr(gridID);
 
   if ( grid->type == gridRef->type || grid->type == GRID_GENERIC )
     {
       if ( grid->size == gridRef->size )
 	{
-	  differ = 0;
+	  differ = false;
 	  if ( grid->type == GRID_LONLAT )
 	    {
 	      /*
@@ -2200,7 +2283,7 @@ int gridCompare(int gridID, const grid_t *grid)
 	      printf("grid.xinc   %f\n", gridInqXinc(gridID));
 	      printf("grid.yinc   %f\n", gridInqYinc(gridID));
 	      */
-	      if ( grid->xsize == gridRef->xsize && grid->ysize == grid->ysize )
+	      if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
 		{
 		  if ( grid->xdef == 2 && grid->ydef == 2 )
 		    {
@@ -2211,17 +2294,17 @@ int gridCompare(int gridID, const grid_t *grid)
 			  if ( IS_NOT_EQUAL(grid->xfirst, gridInqXval(gridID, 0)) ||
 			       IS_NOT_EQUAL(grid->yfirst, gridInqYval(gridID, 0)))
 			    {
-			      differ = 1;
+			      differ = true;
 			    }
 			  if ( !differ && fabs(grid->xinc) > 0 &&
 			       fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000))
 			    {
-			      differ = 1;
+			      differ = true;
 			    }
 			  if ( !differ && fabs(grid->yinc) > 0 &&
 			       fabs(fabs(grid->yinc) - fabs(gridRef->yinc)) > fabs(grid->yinc/1000))
 			    {
-			      differ = 1;
+			      differ = true;
 			    }
 			}
 		    }
@@ -2229,7 +2312,7 @@ int gridCompare(int gridID, const grid_t *grid)
                     differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
 		}
 	      else
-		differ = 1;
+		differ = true;
 	    }
 	  else if ( grid->type == GRID_GENERIC )
 	    {
@@ -2244,7 +2327,7 @@ int gridCompare(int gridID, const grid_t *grid)
 		{
 		}
 	      else
-		differ = 1;
+		differ = true;
 	    }
 	  else if ( grid->type == GRID_GAUSSIAN )
 	    {
@@ -2258,14 +2341,14 @@ int gridCompare(int gridID, const grid_t *grid)
 			     fabs(grid->yfirst - gridInqYval(gridID, 0)) > 0.0015 ||
 			     (fabs(grid->xinc)>0 && fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000)) )
 			  {
-			    differ = 1;
+			    differ = true;
 			  }
 		    }
 		  else if ( grid->xvals && grid->yvals )
                     differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
 		}
 	      else
-		differ = 1;
+		differ = true;
 	    }
 	  else if ( grid->type == GRID_CURVILINEAR )
 	    {
@@ -2359,14 +2442,6 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
   if ( g1->ysize         != g2->ysize        ) return differ;
   if ( g1->lcomplex      != g2->lcomplex     ) return differ;
 
-  if ( g1->rowlon )
-    {
-      for ( i = 0; i < g1->nrowlon; i++ )
-	if ( g1->rowlon[i] != g2->rowlon[i] ) return differ;
-    }
-  else if ( g2->rowlon )
-    return differ;
-
   if ( IS_NOT_EQUAL(g1->xfirst        , g2->xfirst)        ) return differ;
   if ( IS_NOT_EQUAL(g1->yfirst	      , g2->yfirst)        ) return differ;
   if ( IS_NOT_EQUAL(g1->xlast         , g2->xlast)         ) return differ;
@@ -2410,8 +2485,8 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
   else if ( g2_xvals )
     return differ;
 
-  const double *restrict g1_yvals = g1->vtable->inqXValsPtr(g1),
-    *restrict g2_yvals = g2->vtable->inqXValsPtr(g2);
+  const double *restrict g1_yvals = g1->vtable->inqYValsPtr(g1),
+    *restrict g2_yvals = g2->vtable->inqYValsPtr(g2);
   if ( g1_yvals )
     {
       if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
@@ -2624,7 +2699,6 @@ static void gridComplete(grid_t *grid)
       {
 	gridDefNP(gridID, grid->np);
 	gridDefYsize(gridID, grid->ysize);
-
         if ( grid->xdef == 2 )
           {
             double xvals[2] = { grid->xfirst, grid->xlast };
@@ -2694,10 +2768,10 @@ static void gridComplete(grid_t *grid)
   grid->yname[CDI_MAX_NAME - 1] = 0;
   grid->ylongname[CDI_MAX_NAME - 1] = 0;
   grid->yunits[CDI_MAX_NAME - 1] = 0;
-
 }
 
-#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
+#define GRID_STR_SERIALIZE(gridP) { gridP->xdimname, gridP->ydimname,  \
+    gridP->vdimname, gridP->xname, gridP->yname,  \
     gridP->xlongname, gridP->ylongname, \
     gridP->xunits, gridP->yunits }
 
@@ -2783,7 +2857,7 @@ int gridGenerate(const grid_t *grid)
     if ( grid_str_tab[i][0] )
       memcpy(gridptr_str_tab[i], grid_str_tab[i], CDI_MAX_NAME);
   gridComplete(gridptr);
-  return (gridID);
+  return gridID;
 }
 
 static void
@@ -2795,7 +2869,7 @@ grid_copy_base_array_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
   int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
   if ( nrowlon )
     {
-      gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int));
+      gridptrDup->rowlon = (int*) Malloc(nrowlon * sizeof(int));
       memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
     }
 
@@ -2860,7 +2934,6 @@ grid_copy_base_array_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
       gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t));
       memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t));
     }
-
 }
 
 
@@ -2886,7 +2959,7 @@ int gridDuplicate(int gridID)
   grid_t *gridptrnew = gridptr->vtable->copy(gridptr);
   int gridIDnew = reshPut(gridptrnew, &gridOps);
   gridptrnew->self = gridIDnew;
-  return (gridIDnew);
+  return gridIDnew;
 }
 
 
@@ -3039,7 +3112,7 @@ int gridInqNvertex(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->nvertex);
+  return gridptr->nvertex;
 }
 
 static void
@@ -3113,7 +3186,7 @@ gridInqXBoundsSerial(grid_t *gridptr, double *xbounds)
   else
     size = 0;
 
-  return ((int)size);
+  return (int)size;
 }
 
 /*
@@ -3200,7 +3273,7 @@ gridInqYBoundsSerial(grid_t *gridptr, double *ybounds)
   else
     size = 0;
 
-  return ((int)size);
+  return (int)size;
 }
 
 
@@ -3244,7 +3317,7 @@ const double *gridInqYboundsPtr(int gridID)
 }
 
 static void
-printDblsPrefixAutoBrk(FILE *fp, const char prefix[], size_t nbyte0,
+printDblsPrefixAutoBrk(FILE *fp, int dig, const char prefix[], size_t nbyte0,
                        size_t n, const double vals[])
 {
   fputs(prefix, fp);
@@ -3256,7 +3329,7 @@ printDblsPrefixAutoBrk(FILE *fp, const char prefix[], size_t nbyte0,
           fprintf(fp, "\n%*s", (int)nbyte0, "");
           nbyte = nbyte0;
         }
-      nbyte += (size_t)fprintf(fp, "%.9g ", vals[i]);
+      nbyte += (size_t)fprintf(fp, "%.*g ", dig, vals[i]);
     }
   fputs("\n", fp);
 }
@@ -3280,19 +3353,19 @@ printIntsPrefixAutoBrk(FILE *fp, const char prefix[], size_t nbyte0,
 }
 
 static void
-printBounds(FILE *fp, const char prefix[], size_t nbyte0,
+printBounds(FILE *fp, int dig, const char prefix[], size_t nbyte0,
             size_t n, size_t nvertex, const double bounds[])
 {
   fputs(prefix, fp);
   if ( n > 0 )
     {
       for ( size_t iv = 0; iv < nvertex; iv++ )
-        fprintf(fp, "%.9g ", bounds[iv]);
+        fprintf(fp, "%.*g ", dig, bounds[iv]);
       for ( size_t i = 1; i < (size_t)n; i++ )
         {
           fprintf(fp, "\n%*s", (int)nbyte0, "");
           for ( size_t iv = 0; iv < nvertex; iv++ )
-            fprintf(fp, "%.9g ", bounds[i*nvertex+iv]);
+            fprintf(fp, "%.*g ", dig, bounds[i*nvertex+iv]);
         }
       fputs("\n", fp);
     }
@@ -3333,6 +3406,9 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
   int xsize    = gridInqXsize(gridID);
   int ysize    = gridInqYsize(gridID);
   int nvertex  = gridInqNvertex(gridID);
+  int prec     = gridInqPrec(gridID);
+
+  int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
 
   fprintf(fp, "#\n"
           "# gridID %d\n"
@@ -3422,28 +3498,28 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	  {
 	    double a = 0, lon_0 = 0, lat_0 = 0;
 	    gridInqLaea(gridID, &a, &lon_0, &lat_0);
-	    fprintf(fp, "a         = %g\n"
-                    "lon_0     = %g\n"
-                    "lat_0     = %g\n", a, lon_0, lat_0);
+	    fprintf(fp, "a         = %.*g\n"
+                    "lon_0     = %.*g\n"
+                    "lat_0     = %.*g\n", dig, a, dig, lon_0, dig, lat_0);
 	  }
 
 	if ( type == GRID_LCC2 )
 	  {
 	    double a = 0, lon_0 = 0, lat_0 = 0, lat_1 = 0, lat_2 = 0;
 	    gridInqLcc2(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2);
-	    fprintf(fp, "a         = %g\n"
-                    "lon_0     = %g\n"
-                    "lat_0     = %g\n"
-                    "lat_1     = %g\n"
-                    "lat_2     = %g\n",
-                    a, lon_0, lat_0, lat_1, lat_2);
+	    fprintf(fp, "a         = %.*g\n"
+                    "lon_0     = %.*g\n"
+                    "lat_0     = %.*g\n"
+                    "lat_1     = %.*g\n"
+                    "lat_2     = %.*g\n",
+                    dig, a, dig, lon_0, dig, lat_0, dig, lat_1, dig, lat_2);
 	  }
 
 	if ( gridptr->isRotated )
 	  {
-	    if ( xsize > 0 ) fprintf(fp, "xnpole    = %g\n", gridptr->xpole);
-	    if ( ysize > 0 ) fprintf(fp, "ynpole    = %g\n", gridptr->ypole);
-	    if ( IS_NOT_EQUAL(gridptr->angle, 0) ) fprintf(fp, "angle     = %g\n", gridptr->angle);
+	    if ( xsize > 0 ) fprintf(fp, "xnpole    = %.*g\n", dig, gridptr->xpole);
+	    if ( ysize > 0 ) fprintf(fp, "ynpole    = %.*g\n", dig, gridptr->ypole);
+	    if ( IS_NOT_EQUAL(gridptr->angle, 0) ) fprintf(fp, "angle     = %.*g\n", dig, gridptr->angle);
  	  }
 
 	if ( xvals )
@@ -3460,13 +3536,13 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 
 	    if ( IS_NOT_EQUAL(xinc, 0) && opt )
 	      {
-                fprintf(fp, "xfirst    = %g\n"
-                        "xinc      = %g\n", xfirst, xinc);
+                fprintf(fp, "xfirst    = %.*g\n"
+                        "xinc      = %.*g\n", dig, xfirst, dig, xinc);
 	      }
 	    else
 	      {
                 static const char prefix[] = "xvals     = ";
-                printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+                printDblsPrefixAutoBrk(fp, dig, prefix, sizeof(prefix)-1,
                                        (size_t)(xdim > 0 ? xdim : 0), xvals);
 	      }
 	  }
@@ -3474,7 +3550,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	if ( xbounds )
 	  {
             static const char prefix[] = "xbounds   = ";
-            printBounds(fp, prefix, sizeof (prefix),
+            printBounds(fp, dig, prefix, sizeof(prefix)-1,
                         (size_t)(xdim > 0 ? xdim : 0),
                         (size_t)(nvertex > 0 ? nvertex : 0), xbounds);
 	  }
@@ -3492,13 +3568,13 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 
 	    if ( IS_NOT_EQUAL(yinc, 0) && opt )
 	      {
-	  	fprintf(fp, "yfirst    = %g\n"
-                        "yinc      = %g\n", yfirst, yinc);
+	  	fprintf(fp, "yfirst    = %.*g\n"
+                        "yinc      = %.*g\n", dig, yfirst, dig, yinc);
 	      }
 	    else
 	      {
                 static const char prefix[] = "yvals     = ";
-                printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+                printDblsPrefixAutoBrk(fp, dig, prefix, sizeof(prefix)-1,
                                        (size_t)(ydim > 0 ? ydim : 0), yvals);
 	      }
 	  }
@@ -3506,7 +3582,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	if ( ybounds )
 	  {
             static const char prefix[] = "ybounds   = ";
-            printBounds(fp, prefix, sizeof (prefix),
+            printBounds(fp, dig, prefix, sizeof(prefix)-1,
                         (size_t)(ydim > 0 ? ydim : 0),
                         (size_t)(nvertex > 0 ? nvertex : 0), ybounds);
 	  }
@@ -3514,7 +3590,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	if ( area )
 	  {
             static const char prefix[] = "area      = ";
-            printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+            printDblsPrefixAutoBrk(fp, dig, prefix, sizeof(prefix)-1,
                                    (size_t)(gridsize > 0 ? gridsize : 0), area);
 	  }
 
@@ -3523,7 +3599,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
             static const char prefix[] = "rowlon    = ";
             int *rowlon = (int *)Malloc((size_t)ysize*sizeof(int));
             gridInqRowlon(gridID, rowlon);
-            printIntsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+            printIntsPrefixAutoBrk(fp, prefix, sizeof(prefix)-1,
                                    (size_t)(ysize > 0 ? ysize : 0), rowlon);
             Free(rowlon);
           }
@@ -3540,16 +3616,16 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	fprintf(fp,
                 "xsize     = %d\n"
                 "ysize     = %d\n"
-                "originLon = %g\n"
-                "originLat = %g\n"
-                "lonParY   = %g\n"
-                "lat1      = %g\n"
-                "lat2      = %g\n"
-                "xinc      = %g\n"
-                "yinc      = %g\n"
-                "projection = %s\n"
-                , xsize, ysize, originLon, originLat, lonParY, lat1, lat2,
-                xincm, yincm,
+                "originLon = %.*g\n"
+                "originLat = %.*g\n"
+                "lonParY   = %.*g\n"
+                "lat1      = %.*g\n"
+                "lat2      = %.*g\n"
+                "xinc      = %.*g\n"
+                "yinc      = %.*g\n"
+                "projection = %s\n",
+                xsize, ysize, dig, originLon, dig, originLat, dig, lonParY,
+                dig, lat1, dig, lat2, dig, xincm, dig, yincm,
                 (projflag & 128) == 0 ? "northpole" : "southpole");
 	break;
       }
@@ -3588,7 +3664,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
   if ( gridptr->mask )
     {
       static const char prefix[] = "mask      = ";
-      printMask(fp, prefix, sizeof (prefix),
+      printMask(fp, prefix, sizeof(prefix)-1,
                 (size_t)(gridsize > 0 ? gridsize : 0), gridptr->mask);
     }
 }
@@ -3628,7 +3704,7 @@ void gridPrintP ( void * voidptr, FILE * fp )
   if ( gridptr->rowlon )
     {
       static const char prefix[] = "rowlon    = ";
-      printIntsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+      printIntsPrefixAutoBrk(fp, prefix, sizeof(prefix)-1,
                              (size_t)(gridptr->nrowlon > 0
                                       ? gridptr->nrowlon : 0), gridptr->rowlon);
     }
@@ -3636,7 +3712,7 @@ void gridPrintP ( void * voidptr, FILE * fp )
   if ( gridptr->mask_gme )
     {
       static const char prefix[] = "mask_gme  = ";
-      printMask(fp, prefix, sizeof (prefix),
+      printMask(fp, prefix, sizeof(prefix)-1,
                 (size_t)(gridptr->size > 0 ? gridptr->size : 0),
                 gridptr->mask_gme);
     }
@@ -3847,7 +3923,6 @@ void gridDefComplexPacking(int gridID, int lcomplex)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-
   if (gridptr->lcomplex != lcomplex)
     {
       gridptr->lcomplex = (short)(lcomplex != 0);
@@ -3860,7 +3935,7 @@ int gridInqComplexPacking(int gridID)
 {
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->lcomplex);
+  return gridptr->lcomplex;
 }
 
 
@@ -3868,7 +3943,7 @@ void gridDefHasDims(int gridID, int hasdims)
 {
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->hasdims != (hasdims != 0))
+  if ( gridptr->hasdims != (hasdims != 0) )
     {
       gridptr->hasdims = hasdims != 0;
       gridMark4Update(gridID);
@@ -3880,7 +3955,7 @@ int gridInqHasDims(int gridID)
 {
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->hasdims);
+  return gridptr->hasdims;
 }
 
 /*
@@ -3901,7 +3976,7 @@ void gridDefNumber(int gridID, const int number)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->number != number)
+  if ( gridptr->number != number )
     {
       gridptr->number = number;
       gridMark4Update(gridID);
@@ -3947,7 +4022,7 @@ void gridDefPosition(int gridID, int position)
 {
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->position != position)
+  if ( gridptr->position != position )
     {
       gridptr->position = position;
       gridMark4Update(gridID);
@@ -3973,7 +4048,7 @@ int gridInqPosition(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return (gridptr->position);
+  return gridptr->position;
 }
 
 /*
@@ -4024,15 +4099,23 @@ The function @func{gridInqReference} returns the reference URI to an unstructure
 */
 int gridInqReference(int gridID, char *reference)
 {
-  int len = 0;
+  size_t len = 0;
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->reference && reference )
+  if ( gridptr->reference )
     {
-      strcpy(reference, gridptr->reference);
+      len = strlen(gridptr->reference);
+      if ( reference )
+        strcpy(reference, gridptr->reference);
     }
 
-  return (len);
+  return (int)len;
+}
+
+const char *gridInqReferencePtr(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  return gridptr->reference;
 }
 
 /*
@@ -4126,11 +4209,6 @@ static int gridGetComponentFlags(const grid_t * gridP)
   return flags;
 }
 
-
-#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
-    gridP->xlongname, gridP->ylongname, \
-    gridP->xunits, gridP->yunits }
-
 static int
 gridGetPackSize(void * voidP, void *context)
 {
@@ -4684,7 +4762,7 @@ gridCompareSearch(int id, void *res, void *data)
 {
   struct gridCompareSearchState *state = (struct gridCompareSearchState*)data;
   (void)res;
-  if (gridCompare(id, state->queryKey) == 0)
+  if ( gridCompare(id, state->queryKey) == false )
     {
       state->resIDValue = id;
       return CDI_APPLY_STOP;
@@ -4698,23 +4776,23 @@ struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
 {
   /*
     mode: 0 search in vlist and grid table
-          1 search in grid table
+          1 search in grid table only
    */
-  int gridglobdefined = FALSE;
-  int griddefined = FALSE;
+  bool gridglobdefined = false;
+  bool griddefined = false;
   int gridID = CDI_UNDEFID;
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   unsigned ngrids = (unsigned)vlistptr->ngrids;
 
   if ( mode == 0 )
-    for (unsigned index = 0; index < ngrids; index++ )
+    for ( unsigned index = 0; index < ngrids; index++ )
       {
 	if ( (gridID = vlistptr->gridIDs[index]) != UNDEFID )
           {
-            if ( gridCompare(gridID, grid) == 0 )
+            if ( gridCompare(gridID, grid) == false )
               {
-                griddefined = TRUE;
+                griddefined = true;
                 break;
               }
           }
@@ -4733,11 +4811,11 @@ struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
               == CDI_APPLY_STOP)))
         gridID = query.resIDValue;
 
-      if ( mode == 1 && gridglobdefined)
+      if ( mode == 1 && gridglobdefined )
 	for (unsigned index = 0; index < ngrids; index++ )
 	  if ( vlistptr->gridIDs[index] == gridID )
 	    {
-	      gridglobdefined = FALSE;
+	      gridglobdefined = false;
 	      break;
 	    }
     }
diff --git a/libcdi/src/grid.h b/libcdi/src/grid.h
index fea99d7..5ae1682 100644
--- a/libcdi/src/grid.h
+++ b/libcdi/src/grid.h
@@ -2,6 +2,7 @@
 #define _GRID_H
 
 #include "cdi.h"
+#include <stdbool.h>
 
 typedef unsigned char mask_t;
 
@@ -27,10 +28,10 @@ struct gridVirtTable
   const double *(*inqXValsPtr)(grid_t *gridptr);
   const double *(*inqYValsPtr)(grid_t *gridptr);
   /* return if for both grids, all xval and all yval are equal */
-  int (*compareXYFull)(grid_t *gridRef, grid_t *gridTest);
+  bool (*compareXYFull)(grid_t *gridRef, grid_t *gridTest);
   /* return if for both grids, x[0], y[0], x[size-1] and y[size-1] are
    * respectively equal */
-  int (*compareXYAO)(grid_t *gridRef, grid_t *gridTest);
+  bool (*compareXYAO)(grid_t *gridRef, grid_t *gridTest);
   void (*inqArea)(grid_t *gridptr, double *area);
   const double *(*inqAreaPtr)(grid_t *gridptr);
   int (*hasArea)(grid_t *gridptr);
@@ -98,6 +99,9 @@ struct grid_t {
   short   hasdims;
   const char *xstdname;
   const char *ystdname;
+  char    xdimname[CDI_MAX_NAME];
+  char    ydimname[CDI_MAX_NAME];
+  char    vdimname[CDI_MAX_NAME];
   char    xname[CDI_MAX_NAME];
   char    yname[CDI_MAX_NAME];
   char    xlongname[CDI_MAX_NAME];
@@ -126,7 +130,11 @@ const double *gridInqXboundsPtr(int gridID);
 const double *gridInqYboundsPtr(int gridID);
 const double *gridInqAreaPtr(int gridID);
 
-int gridCompare(int gridID, const grid_t *grid);
+const char *gridInqXnamePtr(int gridID);
+const char *gridInqYnamePtr(int gridID);
+
+const char *gridInqReferencePtr(int gridID);
+
 int gridGenerate(const grid_t *grid);
 
 void cdiGridGetIndexList(unsigned, int * );
diff --git a/libcdi/src/mo_cdi.f90 b/libcdi/src/mo_cdi.f90
index 1221ad0..23098dd 100644
--- a/libcdi/src/mo_cdi.f90
+++ b/libcdi/src/mo_cdi.f90
@@ -444,6 +444,17 @@ module mo_cdi
   public :: gridInqXvals
   public :: gridDefYvals
   public :: gridInqYvals
+  integer(c_int), public, parameter :: CDI_GRID_XNAME = 901
+  integer(c_int), public, parameter :: CDI_GRID_YNAME = 902
+  integer(c_int), public, parameter :: CDI_GRID_XDIMNAME = 903
+  integer(c_int), public, parameter :: CDI_GRID_YDIMNAME = 904
+  integer(c_int), public, parameter :: CDI_GRID_VDIMNAME = 905
+  integer(c_int), public, parameter :: CDI_GRID_XLONGNAME = 906
+  integer(c_int), public, parameter :: CDI_GRID_YLONGNAME = 907
+  integer(c_int), public, parameter :: CDI_GRID_XUNITS = 908
+  integer(c_int), public, parameter :: CDI_GRID_YUNITS = 909
+  public :: cdiGridDefString
+  public :: cdiGridInqString
   public :: gridDefXname
   public :: gridInqXname
   public :: gridDefXlongname
@@ -528,6 +539,13 @@ module mo_cdi
   public :: zaxisInqNumber
   public :: zaxisDefUUID
   public :: zaxisInqUUID
+  integer(c_int), public, parameter :: CDI_ZAXIS_NAME = 801
+  integer(c_int), public, parameter :: CDI_ZAXIS_DIMNAME = 802
+  integer(c_int), public, parameter :: CDI_ZAXIS_VDIMNAME = 803
+  integer(c_int), public, parameter :: CDI_ZAXIS_LONGNAME = 804
+  integer(c_int), public, parameter :: CDI_ZAXIS_UNITS = 805
+  public :: cdiZaxisDefString
+  public :: cdiZaxisInqString
   public :: zaxisDefName
   public :: zaxisInqName
   public :: zaxisDefLongname
@@ -4901,6 +4919,73 @@ contains
     end if
   end function gridNamePtr
 
+  function cdiGridDefString(gridID_dummy, key_dummy, size_dummy, mesg_dummy)&
+  & result(f_result)
+    integer(c_int) :: f_result
+    integer(c_int), value :: gridID_dummy
+    integer(c_int), value :: key_dummy
+    integer(c_int), value :: size_dummy
+    character(kind = c_char, len = *), intent(in) :: mesg_dummy
+    character(kind = c_char) :: mesg_temp(len(mesg_dummy) + 1)
+    integer :: mesg_i
+    interface
+      function lib_cdiGridDefString(gridID_dummy, key_dummy, size_dummy,&
+      & mesg_dummy) bind(c, name = 'cdiGridDefString') result(c_result)
+        import c_char, c_int
+        integer(c_int) :: c_result
+        integer(c_int), value :: gridID_dummy
+        integer(c_int), value :: key_dummy
+        integer(c_int), value :: size_dummy
+        character(kind = c_char) :: mesg_dummy(*)
+      end function lib_cdiGridDefString
+    end interface
+    do mesg_i = 1, len(mesg_dummy)
+      mesg_temp(mesg_i) = mesg_dummy(mesg_i:mesg_i)
+    end do
+    mesg_temp(len(mesg_dummy) + 1) = c_null_char
+    f_result = lib_cdiGridDefString(gridID_dummy, key_dummy, size_dummy,&
+    & mesg_temp)
+  end function cdiGridDefString
+
+  function cdiGridInqString(gridID_dummy, key_dummy, size_dummy, mesg_dummy)&
+  & result(f_result)
+    integer(c_int) :: f_result
+    integer(c_int), value :: gridID_dummy
+    integer(c_int), value :: key_dummy
+    integer(c_int), value :: size_dummy
+    character(kind = c_char, len = *), intent(inout) :: mesg_dummy
+    character(kind = c_char) :: mesg_temp(len(mesg_dummy) + 1)
+    integer :: mesg_i
+    interface
+      function lib_cdiGridInqString(gridID_dummy, key_dummy, size_dummy,&
+      & mesg_dummy) bind(c, name = 'cdiGridInqString') result(c_result)
+        import c_char, c_int
+        integer(c_int) :: c_result
+        integer(c_int), value :: gridID_dummy
+        integer(c_int), value :: key_dummy
+        integer(c_int), value :: size_dummy
+        character(kind = c_char) :: mesg_dummy(*)
+      end function lib_cdiGridInqString
+    end interface
+    mesg_temp(len(mesg_dummy) + 1) = c_null_char
+    do mesg_i = len(mesg_dummy), 1, -1
+      if(mesg_dummy(mesg_i:mesg_i) /= ' ') exit
+      mesg_temp(mesg_i) = c_null_char
+    end do
+    do mesg_i = mesg_i, 1, -1
+        mesg_temp(mesg_i) = mesg_dummy(mesg_i:mesg_i)
+    end do
+    f_result = lib_cdiGridInqString(gridID_dummy, key_dummy, size_dummy,&
+    & mesg_temp)
+    do mesg_i = 1, len(mesg_dummy)
+      if(mesg_temp(mesg_i) == c_null_char) exit
+      mesg_dummy(mesg_i:mesg_i) = mesg_temp(mesg_i)
+    end do
+    do mesg_i = mesg_i, len(mesg_dummy)
+      mesg_dummy(mesg_i:mesg_i) = ' '
+    end do
+  end function cdiGridInqString
+
   subroutine gridDefXname(gridID_dummy, xname_dummy)
     integer(c_int), value :: gridID_dummy
     character(kind = c_char, len = *), intent(in) :: xname_dummy
@@ -5353,6 +5438,73 @@ contains
     end do
   end subroutine zaxisName
 
+  function cdiZaxisDefString(zaxisID_dummy, key_dummy, size_dummy, mesg_dummy)&
+  & result(f_result)
+    integer(c_int) :: f_result
+    integer(c_int), value :: zaxisID_dummy
+    integer(c_int), value :: key_dummy
+    integer(c_int), value :: size_dummy
+    character(kind = c_char, len = *), intent(in) :: mesg_dummy
+    character(kind = c_char) :: mesg_temp(len(mesg_dummy) + 1)
+    integer :: mesg_i
+    interface
+      function lib_cdiZaxisDefString(zaxisID_dummy, key_dummy, size_dummy,&
+      & mesg_dummy) bind(c, name = 'cdiZaxisDefString') result(c_result)
+        import c_char, c_int
+        integer(c_int) :: c_result
+        integer(c_int), value :: zaxisID_dummy
+        integer(c_int), value :: key_dummy
+        integer(c_int), value :: size_dummy
+        character(kind = c_char) :: mesg_dummy(*)
+      end function lib_cdiZaxisDefString
+    end interface
+    do mesg_i = 1, len(mesg_dummy)
+      mesg_temp(mesg_i) = mesg_dummy(mesg_i:mesg_i)
+    end do
+    mesg_temp(len(mesg_dummy) + 1) = c_null_char
+    f_result = lib_cdiZaxisDefString(zaxisID_dummy, key_dummy, size_dummy,&
+    & mesg_temp)
+  end function cdiZaxisDefString
+
+  function cdiZaxisInqString(zaxisID_dummy, key_dummy, size_dummy, mesg_dummy)&
+  & result(f_result)
+    integer(c_int) :: f_result
+    integer(c_int), value :: zaxisID_dummy
+    integer(c_int), value :: key_dummy
+    integer(c_int), value :: size_dummy
+    character(kind = c_char, len = *), intent(inout) :: mesg_dummy
+    character(kind = c_char) :: mesg_temp(len(mesg_dummy) + 1)
+    integer :: mesg_i
+    interface
+      function lib_cdiZaxisInqString(zaxisID_dummy, key_dummy, size_dummy,&
+      & mesg_dummy) bind(c, name = 'cdiZaxisInqString') result(c_result)
+        import c_char, c_int
+        integer(c_int) :: c_result
+        integer(c_int), value :: zaxisID_dummy
+        integer(c_int), value :: key_dummy
+        integer(c_int), value :: size_dummy
+        character(kind = c_char) :: mesg_dummy(*)
+      end function lib_cdiZaxisInqString
+    end interface
+    mesg_temp(len(mesg_dummy) + 1) = c_null_char
+    do mesg_i = len(mesg_dummy), 1, -1
+      if(mesg_dummy(mesg_i:mesg_i) /= ' ') exit
+      mesg_temp(mesg_i) = c_null_char
+    end do
+    do mesg_i = mesg_i, 1, -1
+        mesg_temp(mesg_i) = mesg_dummy(mesg_i:mesg_i)
+    end do
+    f_result = lib_cdiZaxisInqString(zaxisID_dummy, key_dummy, size_dummy,&
+    & mesg_temp)
+    do mesg_i = 1, len(mesg_dummy)
+      if(mesg_temp(mesg_i) == c_null_char) exit
+      mesg_dummy(mesg_i:mesg_i) = mesg_temp(mesg_i)
+    end do
+    do mesg_i = mesg_i, len(mesg_dummy)
+      mesg_dummy(mesg_i:mesg_i) = ' '
+    end do
+  end function cdiZaxisInqString
+
   subroutine zaxisDefName(zaxisID_dummy, name)
     integer(c_int), value :: zaxisID_dummy
     character(kind = c_char, len = *), optional, intent(in) :: name
diff --git a/libcdi/src/pio_client.c b/libcdi/src/pio_client.c
index 100e25d..7c2ee99 100644
--- a/libcdi/src/pio_client.c
+++ b/libcdi/src/pio_client.c
@@ -79,7 +79,7 @@ cdiPioClientStreamOpen(const char *filename, char filemode,
         }
     }
   else
-    Error("cdiPIO read support not implemented");
+    xabort("cdiPIO read support not implemented");
   return fileID;
 }
 
diff --git a/libcdi/src/pio_comm.c b/libcdi/src/pio_comm.c
index b5cef8b..61446e6 100644
--- a/libcdi/src/pio_comm.c
+++ b/libcdi/src/pio_comm.c
@@ -116,19 +116,19 @@ pioInfoInit(pioInfo_t *p, MPI_Comm commGlob, int clientServerRole)
     int nProcsIO;
     {
       enum { numGlobSums = 4 };
-      int temp[numGlobSums] = {
+      int iBuf[numGlobSums] = {
         isProcIO,
         (clientServerRole & PIO_ROLE_COLLECTOR),
         globRankOfGroupLeader[0],
         globRankOfGroupLeader[1]
       };
-      xmpi(MPI_Allreduce(MPI_IN_PLACE, temp, numGlobSums, MPI_INT, MPI_SUM,
+      xmpi(MPI_Allreduce(MPI_IN_PLACE, iBuf, numGlobSums, MPI_INT, MPI_SUM,
                          commGlob));
-      p->sizePio = nProcsIO = temp[0];
+      p->sizePio = nProcsIO = iBuf[0];
       p->sizeCalc = p->sizeGlob - nProcsIO;
-      p->sizeColl = temp[1];
-      globRankOfGroupLeader[0] = temp[2];
-      globRankOfGroupLeader[1] = temp[3];
+      p->sizeColl = iBuf[1];
+      globRankOfGroupLeader[0] = iBuf[2];
+      globRankOfGroupLeader[1] = iBuf[3];
     }
     if (isProcIO)
       {
@@ -278,15 +278,6 @@ int      commInqIsProcIO     ( void )
   return info->isProcIO;
 }
 
-
-int commInqNProcsModel ( void )
-{
-  xassert ( info != NULL &&
-           info->sizeCalc != -1 );
-  return info->sizeCalc;
-}
-
-
 int commInqIOMode(void)
 {
   return info != NULL ? info->IOMode : PIO_NONE;
diff --git a/libcdi/src/pio_comm.h b/libcdi/src/pio_comm.h
index 994de25..495b79e 100644
--- a/libcdi/src/pio_comm.h
+++ b/libcdi/src/pio_comm.h
@@ -48,7 +48,7 @@ void     commPrint              ( FILE * );
 /* query rank of collector responsible for client on inter-communicator
  * returns -1 on server processes.
  */
-int cdiPioInqCollectorOfClient();
+int cdiPioInqCollectorOfClient(void);
 
 /* query communicator containing clients and collectors,
  * the collectors occupy the top-ranks
diff --git a/libcdi/src/pio_interface.c b/libcdi/src/pio_interface.c
index 9115b47..da371c6 100644
--- a/libcdi/src/pio_interface.c
+++ b/libcdi/src/pio_interface.c
@@ -106,7 +106,7 @@ modelWinFlushBuffer(size_t streamIdx)
   txWin[streamIdx].dictRPCUsed = 0;
   txWin[streamIdx].pendingUpdate = false;
   txWin[streamIdx].postSet = false;
-  *(struct winHeaderEntry *)txWin[streamIdx].buffer
+  *(struct winHeaderEntry *)(void *)txWin[streamIdx].buffer
     = (struct winHeaderEntry){
     .id = HEADERSIZEMARKER,
     .specific.headerSize = { .numDataEntries = 0, .numRPCEntries = 0 },
@@ -201,13 +201,13 @@ modelWinEnqueue(size_t streamIdx,
     }
   else if (header.id == PARTDESCMARKER)
     {
-      Xt_uid uid = header.specific.partDesc.uid;
+      Xt_uid uid = unpackXTUID(header.specific.partDesc.packedUID);
       int offset = -1;
       /* search if same uid entry has already been enqueued */
       for (int entry = 2; entry < targetEntry; entry += 2)
         {
           xassert(winDict[entry].id == PARTDESCMARKER);
-          if (winDict[entry].specific.partDesc.uid == uid)
+          if (unpackXTUID(winDict[entry].specific.partDesc.packedUID) == uid)
             {
               offset = winDict[entry].offset;
               break;
@@ -299,8 +299,9 @@ pioBufferPartData_(int streamID, int varID,
   {
     struct winHeaderEntry partHeader
       = { .id = PARTDESCMARKER,
-          .specific.partDesc = { .uid = xt_idxlist_get_uid(partDesc) },
           .offset = 0 };
+    packXTUID(partHeader.specific.partDesc.packedUID,
+              xt_idxlist_get_uid(partDesc));
     modelWinEnqueue(streamIdx, partHeader, partDesc, cdiPio_xt_idxlist_pack_wrap);
   }
   txWin[streamIdx].refuseFuncCall = 1;
diff --git a/libcdi/src/pio_mpi_fw_at_reblock.c b/libcdi/src/pio_mpi_fw_at_reblock.c
index 961ef34..e945fda 100644
--- a/libcdi/src/pio_mpi_fw_at_reblock.c
+++ b/libcdi/src/pio_mpi_fw_at_reblock.c
@@ -300,9 +300,9 @@ flushReblockBuffer(aFiledataM *of, int blockBufIdx)
       xmpi(MPI_Waitany(numMsg, of->reqs, &finIdx, MPI_STATUS_IGNORE));
       if (finIdx != MPI_UNDEFINED)
         {
-          int blockBufIdx = of->msgs[finIdx].pos;
-          if (blockBufIdx >= 0 && of->msgs[finIdx].direction == RECV)
-            --(of->pending[blockBufIdx].incoming);
+          int blockBufIdxOfTx = of->msgs[finIdx].pos;
+          if (blockBufIdxOfTx >= 0 && of->msgs[finIdx].direction == RECV)
+            --(of->pending[blockBufIdxOfTx].incoming);
           else if (of->msgs[finIdx].direction == SEND)
             Free(of->msgs[finIdx].sendBuf);
           else
@@ -364,10 +364,10 @@ fwFileWriteAtReblock(int fileID, const void *buffer, size_t len)
   int numBlockBuf = of->numBlockBuf;
   int numMsg = of->numMsg;
   const unsigned char *inBuf = buffer;
-  const unsigned char *directWriteBuf;
+  const unsigned char *directWriteBuf = NULL;
   /* positive value iff direct write occurs */
   int directWriteSize = -1;
-  MPI_Offset directWriteOfs;
+  MPI_Offset directWriteOfs = 0;
   for (int collRank = 0; collRank < sizePio; ++collRank)
     if (of->collWriteSize[collRank])
     {
diff --git a/libcdi/src/pio_posixnonb.c b/libcdi/src/pio_posixnonb.c
index c16ea30..eb8d67e 100644
--- a/libcdi/src/pio_posixnonb.c
+++ b/libcdi/src/pio_posixnonb.c
@@ -125,7 +125,6 @@ pioWriterStdIO(void)
 {
   bFiledataP *bfd;
   listSet * bibBFiledataP;
-  size_t amount;
   int messagesize, source, tag, id;
   struct fileOpTag rtag;
   MPI_Status status;
@@ -201,47 +200,46 @@ pioWriterStdIO(void)
 	  break;
 
 	case IO_Send_buffer:
+          {
+            if (!(bfd = listSetGet(bibBFiledataP, fileIDTest,
+                                   (void *)(intptr_t)rtag.id)))
+              xabort("fileID=%d is not in set", rtag.id );
+            size_t amount = (size_t)messagesize;
 
-          if (!(bfd = listSetGet(bibBFiledataP, fileIDTest,
-                               (void *)(intptr_t)rtag.id)))
-            xabort("fileID=%d is not in set", rtag.id );
-
-	  amount = (size_t)messagesize;
-
-	  xdebug("COMMAND %s, ID=%d, NAME=%s", cdiPioCmdStrTab[rtag.command],
-                 rtag.id, bfd->name);
+            xdebug("COMMAND %s, ID=%d, NAME=%s", cdiPioCmdStrTab[rtag.command],
+                   rtag.id, bfd->name);
 
-	  xmpi(MPI_Recv(bfd->fb->buffer, messagesize, MPI_UNSIGNED_CHAR,
-                        source, tag, commPio, &status));
+            xmpi(MPI_Recv(bfd->fb->buffer, messagesize, MPI_UNSIGNED_CHAR,
+                          source, tag, commPio, &status));
 
-	  writeP(bfd, amount);
-	  break;
+            writeP(bfd, amount);
+          }
+          break;
 
 	case IO_Close_file:
+          {
+            xdebug("COMMAND %s,  FILE%d, SOURCE%d",
+                   cdiPioCmdStrTab[rtag.command], rtag.id, source);
 
-	  xdebug("COMMAND %s,  FILE%d, SOURCE%d",
-                 cdiPioCmdStrTab[rtag.command], rtag.id, source);
-
-          if (!(bfd = listSetGet(bibBFiledataP, fileIDTest,
-                               (void *)(intptr_t)rtag.id)))
-            xabort("fileID=%d is not in set", rtag.id);
-
-          amount = (size_t)messagesize;
-
-	  xdebug("COMMAND %s, ID=%d, NAME=%s, AMOUNT=%zu",
-                 cdiPioCmdStrTab[rtag.command], rtag.id, bfd->name, amount);
+            if (!(bfd = listSetGet(bibBFiledataP, fileIDTest,
+                                   (void *)(intptr_t)rtag.id)))
+              xabort("fileID=%d is not in set", rtag.id);
+            size_t amount = (size_t)messagesize;
+            xdebug("COMMAND %s, ID=%d, NAME=%s, AMOUNT=%zu",
+                   cdiPioCmdStrTab[rtag.command], rtag.id, bfd->name, amount);
 
-	  xmpi(MPI_Recv(bfd->fb->buffer, messagesize, MPI_UNSIGNED_CHAR,
-                        source, tag, commPio, &status));
+            xmpi(MPI_Recv(bfd->fb->buffer, messagesize, MPI_UNSIGNED_CHAR,
+                          source, tag, commPio, &status));
 
-	  writeP ( bfd, amount );
+            writeP ( bfd, amount );
 
-	  if ( ! --(bfd->activeCollectors))
-	    {
-	      xdebug("all are finished with file %d, delete node", rtag.id);
-	      listSetRemove(bibBFiledataP, fileIDTest,
-                            (void *)(intptr_t)rtag.id);
-	    }
+            if ( ! --(bfd->activeCollectors))
+              {
+                xdebug("all are finished with file %d, delete node", rtag.id);
+                listSetRemove(bibBFiledataP, fileIDTest,
+                              (void *)(intptr_t)rtag.id);
+              }
+          }
           break;
         case IO_Finalize:
           {
diff --git a/libcdi/src/pio_rpc.c b/libcdi/src/pio_rpc.c
index 4c7a838..38389a1 100644
--- a/libcdi/src/pio_rpc.c
+++ b/libcdi/src/pio_rpc.c
@@ -28,9 +28,9 @@ computeClientStreamBufSize(int streamID, const struct collSpec *collector)
       size_t chunkSize;
       {
         int varSize = vlistInqVarSize(vlistID, (int)varID);
-        chunkSize = (size_t)ceilf(cdiPIOpartInflate_
-                                    * (float)varSize
-                                    / (float)collector->numClients);
+        chunkSize = (size_t)(ceilf(cdiPIOpartInflate_
+                                   * (float)varSize
+                                   / (float)collector->numClients));
       }
       rmaSizeSpec.numDataRecords += 2;
       rmaSizeSpec.bufSize += chunkSize * sizeof (double)
diff --git a/libcdi/src/pio_rpc.h b/libcdi/src/pio_rpc.h
index f96ee64..df1a953 100644
--- a/libcdi/src/pio_rpc.h
+++ b/libcdi/src/pio_rpc.h
@@ -5,6 +5,7 @@
 #  include "config.h"
 #endif
 
+#include <limits.h>
 #include <stdbool.h>
 
 #include <mpi.h>
@@ -54,13 +55,38 @@ union funcArgs
   } streamNewTimestep;
 };
 
+enum {
+  /* number of unsigned vector elements to pack an Xt_uid into */
+  uidInts = (sizeof(Xt_uid) + sizeof(unsigned) - 1)/sizeof (unsigned),
+  packUIDShift = (sizeof (unsigned) % sizeof(Xt_uid)) * CHAR_BIT,
+};
 /* Describes offset and ID of serialized partition descriptor.
  * partDescMarker == PARTDESCMARKER, always. */
 struct partDescRecord
 {
-  Xt_uid uid;
+  unsigned packedUID[uidInts];
 };
 
+static inline void
+packXTUID(unsigned *restrict packedUID, Xt_uid uid)
+{
+  for (size_t i = 0; i < uidInts; ++i)
+    {
+      packedUID[i] = uid & ~0U;
+      uid >>= packUIDShift;
+    }
+}
+
+static inline Xt_uid
+unpackXTUID(const unsigned *packedUID)
+{
+  Xt_uid uid = 0;
+  for (size_t i = uidInts; i > 0; --i)
+    uid = (uid << packUIDShift) | packedUID[i - 1];
+  return uid;
+}
+
+
 struct winHeaderEntry
 {
   int id;
diff --git a/libcdi/src/pio_server.c b/libcdi/src/pio_server.c
index 050a6ec..74aad92 100644
--- a/libcdi/src/pio_server.c
+++ b/libcdi/src/pio_server.c
@@ -83,7 +83,6 @@ struct recordWrite
 };
 
 struct streamMapping {
-  int numVars;
   /* data entry varMap[i] contains data for variable i or -1 if no
    * data entry for i has been transferred */
   int *varMap;
@@ -93,6 +92,7 @@ struct streamMapping {
   /* nMiss[i] = missing values were provided for variable i */
   int *hasMissing;
   int numWrittenRecords;
+  int numVars;
   struct streamMemLayout *layout;
   struct recordWrite writtenRecords[];
 };
@@ -203,6 +203,8 @@ resizeVarGatherBuf(int size, double **buf, int *bufSize)
     *buf = Realloc(*buf, (size_t)(*bufSize = size) * sizeof (buf[0][0]));
 }
 
+#define wHECast struct winHeaderEntry *)(void *
+
 static Xt_redist
 buildVarRedist(int headerIdx, size_t streamIdx,
                /* index list representing the data elements gathered on
@@ -212,7 +214,7 @@ buildVarRedist(int headerIdx, size_t streamIdx,
 {
   const struct clientBuf *restrict clientBuf = rxWin[streamIdx].clientBuf;
   const struct winHeaderEntry *winDict
-    = (struct winHeaderEntry *)clientBuf[0].mem;
+    = (wHECast)clientBuf[0].mem;
   int streamID = openStreams.entries[streamIdx];
   int varID = winDict[headerIdx].specific.dataRecord.varID;
   struct Xt_offset_ext *partExts
@@ -224,14 +226,11 @@ buildVarRedist(int headerIdx, size_t streamIdx,
     {
       unsigned char *clientMem = clientBuf[clientIdx].mem;
       struct dataRecord *dataHeader
-        = &((struct winHeaderEntry *)clientMem)[headerIdx].specific.dataRecord;
-      int position = ((struct winHeaderEntry *)clientMem)[headerIdx + 1].offset;
-      xassert(namespaceAdaptKey2(((struct winHeaderEntry *)
-                                  clientMem)[headerIdx].id)
-              == streamID
+        = &((wHECast)clientMem)[headerIdx].specific.dataRecord;
+      int position = ((wHECast)clientMem)[headerIdx + 1].offset;
+      xassert(namespaceAdaptKey2(((wHECast)clientMem)[headerIdx].id) == streamID
               && dataHeader->varID == varID
-              && (((struct winHeaderEntry *)clientMem)[headerIdx + 1].id
-                  == PARTDESCMARKER)
+              && (((wHECast)clientMem)[headerIdx + 1].id == PARTDESCMARKER)
               && position > 0
               && ((size_t)position
                   >= sizeof (struct winHeaderEntry)
@@ -243,8 +242,7 @@ buildVarRedist(int headerIdx, size_t streamIdx,
       unsigned partSize
         = (unsigned)xt_idxlist_get_num_indices(part[clientIdx]);
       size_t charOfs = (size_t)((clientMem
-                                 + ((struct winHeaderEntry *)
-                                    clientMem)[headerIdx].offset)
+                                 + ((wHECast)clientMem)[headerIdx].offset)
                                 - clientBuf[0].mem);
       xassert(charOfs % sizeof (double) == 0
               && charOfs / sizeof (double) + partSize <= INT_MAX);
@@ -568,7 +566,7 @@ writeNetCDFStream(size_t streamIdx,
 static inline struct winHeaderEntry *
 winDictEntry(size_t streamIdx, size_t client, size_t entry)
 {
-  return ((struct winHeaderEntry *)rxWin[streamIdx].clientBuf[client].mem)
+  return ((wHECast)rxWin[streamIdx].clientBuf[client].mem)
     + entry;
 }
 
@@ -592,7 +590,7 @@ getLayout(size_t streamIdx)
           = winDictEntry(streamIdx, client, headerIdx);
         size_t varID = (size_t)varHeader[0].specific.dataRecord.varID;
         size_t offset = (size_t)varHeader[0].offset;
-        Xt_uid uid = varHeader[1].specific.partDesc.uid;
+        Xt_uid uid = unpackXTUID(varHeader[1].specific.partDesc.packedUID);
         layout[client][varID] = (struct streamMemLayout){
           .varPartIdxListUID = uid, .offset = offset };
       }
@@ -746,14 +744,10 @@ struct passPlan
   int varStart, varEnd;
 };
 
-void
-deco1D_CCP(size_t n, const size_t weightPfxSums[n],
-           size_t nparts, size_t separators[nparts + 1]);
-
 /**
- * @param[out] passes pointer to pointer to 2-dimensional array of
+ * @param[out] passes_ pointer to pointer to 2-dimensional array of
  * records of dimensions $number of passes \cdot number of collectors$,
- * where $(*passes)[pass][i]$ details the records written by collector
+ * where $(*passes_)[pass][i]$ details the records written by collector
  * rank \a i
  * @return number of passes
  */
@@ -795,8 +789,8 @@ planPasses(size_t streamIdx, const struct streamMapping *mapping,
        * instead */
       numPasses = 1;
       struct passPlan *passes = Malloc(sizeof (*passes) * collSize);
-      deco1D_CCP(numWrittenRecords, recordDataSizePfxSums,
-                 collSize, recordSeparations);
+      cdiPioDeco1D_CCP(numWrittenRecords, recordDataSizePfxSums,
+                       collSize, recordSeparations);
       for (size_t rank = 0; rank < collSize; ++rank)
         {
           size_t startRecord = recordSeparations[rank],
@@ -850,18 +844,6 @@ planPasses(size_t streamIdx, const struct streamMapping *mapping,
   return numPasses;
 }
 
-static inline unsigned
-umax(unsigned a, unsigned b)
-{
-  return a >= b ? a : b;
-}
-
-static inline unsigned
-umin(unsigned a, unsigned b)
-{
-  return a <= b ? a : b;
-}
-
 static inline size_t
 szmin(size_t a, size_t b)
 {
@@ -1059,7 +1041,7 @@ writeGribStream(size_t streamIdx,
       {
         size_t varIdx = (size_t)-1;
         int varID = -1;
-        size_t base = 0;
+        size_t recordDataOfs = 0;
         const double *data = *data_;
         for (size_t recordIdx = myRecordStart;
              recordIdx <= myRecordEnd;
@@ -1073,9 +1055,9 @@ writeGribStream(size_t streamIdx,
             size_t nvals = recordSize / sizeof (double);
             int nmiss
               = countVarChunkMissingVals(vlistID, varID, mapping, (int)nvals,
-                                         data + base);
-            streamWriteVarSlice(streamID, varID, level, data + base, nmiss);
-            base += nvals;
+                                         data + recordDataOfs);
+            streamWriteVarSlice(streamID, varID, level, data + recordDataOfs, nmiss);
+            recordDataOfs += nvals;
           }
         aggBufFlush(streamIdx, cdiPioFileWrite);
       }
@@ -1098,7 +1080,7 @@ readGetBuffers(size_t streamIdx, const struct cdiPioConf *conf)
   xdebug("%s", "START");
 
   struct winHeaderEntry *winDict
-    = (struct winHeaderEntry *)rxWin[streamIdx].clientBuf[0].mem;
+    = (wHECast)rxWin[streamIdx].clientBuf[0].mem;
   xassert(winDict[0].id == HEADERSIZEMARKER);
   {
     int dictSize = rxWin[streamIdx].clientBuf[0].dictSize,
@@ -1203,7 +1185,7 @@ cdiPioServerStreamOpen(const char *filename, char filemode,
                        int filetype, stream_t *streamptr,
                        int recordBufIsToBeCreated)
 {
-  int fileID;
+  int fileID = -1;
 #if defined HAVE_LIBNETCDF && ! defined HAVE_PARALLEL_NC4
   /* Only needs initialization to shut up gcc */
   int rank = -1;
diff --git a/libcdi/src/pio_util.c b/libcdi/src/pio_util.c
index 811e321..8225d2c 100644
--- a/libcdi/src/pio_util.c
+++ b/libcdi/src/pio_util.c
@@ -198,8 +198,8 @@ cdiPioQueryVarDims(int varShape[3], int vlistID, int varID)
 
 
 void
-deco1D_CCP(size_t nelems, const size_t *restrict weightPfxSums,
-           size_t nparts, size_t *restrict separators)
+cdiPioDeco1D_CCP(size_t nelems, const size_t *restrict weightPfxSums,
+                 size_t nparts, size_t *restrict separators)
 {
   separators[0] = 0;
   separators[nparts] = nelems;
diff --git a/libcdi/src/pio_util.h b/libcdi/src/pio_util.h
index 6be66af..47ff0a8 100644
--- a/libcdi/src/pio_util.h
+++ b/libcdi/src/pio_util.h
@@ -105,6 +105,10 @@ void printArray ( const char *, const char *, const void *, int, int, const char
 int
 cdiPioQueryVarDims(int varShape[3], int vlistID, int varID);
 
+void
+cdiPioDeco1D_CCP(size_t n, const size_t weightPfxSums[n],
+                 size_t nparts, size_t separators[nparts + 1]);
+
 #endif
 /*
  * Local Variables:
diff --git a/libcdi/src/pkgconfig/cdi.pc.in b/libcdi/src/pkgconfig/cdi.pc.in
index 19a2ae8..0cbd19e 100644
--- a/libcdi/src/pkgconfig/cdi.pc.in
+++ b/libcdi/src/pkgconfig/cdi.pc.in
@@ -4,16 +4,11 @@ libdir=@libdir@
 includedir=@includedir@
 cflags=-I at includedir@
 fcflags=@FPP_INCOPT@@includedir@ @CDI_F90_INTERFACE_FCFLAGS@
-libs=-L at libdir@ -lcdi @GRIB_API_LIBS@ @JASPER_LIBS@ @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@ @THREADS_LIBS@
+libs=-L at libdir@ -lcdi @GRIB_API_LIBS@ @JASPER_LIBS@ @NETCDF_LIBS@ @SZLIB_LIBS@ @THREADS_LIBS@
 threads_libs=@THREADS_LIBS@
 threads_cflags=@THREADS_INCLUDE@
-zlib_cflags=@ZLIB_INCLUDE@
-zlib_libs=@ZLIB_LIBS@
 szlib_cflags=@SZLIB_INCLUDE@
 szlib_libs=@SZLIB_LIBS@
-hdf5_root=@HDF5_ROOT@
-hdf5_cflags=@HDF5_INCLUDE@
-hdf5_libs=@HDF5_LIBS@
 netcdf_root=@NETCDF_ROOT@
 netcdf_cflags=@NETCDF_INCLUDE@
 netcdf_libs=@NETCDF_LIBS@
diff --git a/libcdi/src/pkgconfig/cdipio.pc.in b/libcdi/src/pkgconfig/cdipio.pc.in
index 27a8c17..b8020c8 100644
--- a/libcdi/src/pkgconfig/cdipio.pc.in
+++ b/libcdi/src/pkgconfig/cdipio.pc.in
@@ -4,16 +4,11 @@ libdir=@libdir@
 includedir=@includedir@
 cflags=-I at includedir@
 fcflags=@FPP_INCOPT@@includedir@ @CDI_F90_INTERFACE_FCFLAGS@
-libs=-L at libdir@ -lcdipio @PPM_CORE_LIBS@ @YAXT_LIBS@ -lcdi @GRIB_API_LIBS@ @JASPER_LIBS@ @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@ @THREADS_LIBS@
+libs=-L at libdir@ -lcdipio @PPM_CORE_LIBS@ @YAXT_LIBS@ -lcdi @GRIB_API_LIBS@ @JASPER_LIBS@ @NETCDF_LIBS@ @SZLIB_LIBS@ @THREADS_LIBS@
 threads_libs=@THREADS_LIBS@
 threads_cflags=@THREADS_INCLUDE@
-zlib_cflags=@ZLIB_INCLUDE@
-zlib_libs=@ZLIB_LIBS@
 szlib_cflags=@SZLIB_INCLUDE@
 szlib_libs=@SZLIB_LIBS@
-hdf5_root=@HDF5_ROOT@
-hdf5_cflags=@HDF5_INCLUDE@
-hdf5_libs=@HDF5_LIBS@
 netcdf_root=@NETCDF_ROOT@
 netcdf_cflags=@NETCDF_INCLUDE@
 netcdf_libs=@NETCDF_LIBS@
diff --git a/libcdi/src/stream.c b/libcdi/src/stream.c
index 79e5ecc..c6467c2 100644
--- a/libcdi/src/stream.c
+++ b/libcdi/src/stream.c
@@ -85,12 +85,12 @@ int cdiGetFiletype(const char *filename, int *byteorder)
   if ( fileID == CDI_UNDEFID )
     {
       if ( strncmp(filename, "http:", 5) == 0 || strncmp(filename, "https:", 6) == 0 )
-	return (FILETYPE_NC);
+	return FILETYPE_NC;
       else
-	return (CDI_ESYSTEM);
+	return CDI_ESYSTEM;
     }
 
-  if ( fileRead(fileID, buffer, 8) != 8 ) return (CDI_EUFTYPE);
+  if ( fileRead(fileID, buffer, 8) != 8 ) return CDI_EUFTYPE;
 
   fileRewind(fileID);
 
@@ -164,7 +164,7 @@ int cdiGetFiletype(const char *filename, int *byteorder)
 
   *byteorder = getByteorder(swap);
 
-  return (filetype);
+  return filetype;
 }
 
 /*
@@ -189,7 +189,7 @@ The valid CDI file format types are @func{FILETYPE_GRB}, @func{FILETYPE_GRB2}, @
 int streamInqFiletype(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  return (streamptr->filetype);
+  return streamptr->filetype;
 }
 
 
@@ -210,7 +210,7 @@ int getByteswap(int byteorder)
       Error("unexpected byteorder %d query!", byteorder);
     }
 
-  return (byteswap);
+  return byteswap;
 }
 
 /*
@@ -289,7 +289,7 @@ The valid CDI byte order types are @func{CDI_BIGENDIAN} and @func{CDI_LITTLEENDI
 int streamInqByteorder(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  return (streamptr->byteorder);
+  return streamptr->byteorder;
 }
 
 
@@ -303,16 +303,16 @@ const char *streamFilesuffix(int filetype)
   int size = (int)(sizeof(fileSuffix)/sizeof(fileSuffix[0]));
 
   if ( filetype > 0 && filetype < size )
-    return (fileSuffix[filetype]);
+    return fileSuffix[filetype];
   else
-    return (fileSuffix[0]);
+    return fileSuffix[0];
 }
 
 
 const char *streamFilename(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  return (streamptr->filename);
+  return streamptr->filename;
 }
 
 static
@@ -326,7 +326,7 @@ long cdiInqTimeSize(int streamID)
     while ( (nrecs = streamInqTimestep(streamID, tsID++)) )
       ntsteps = streamptr->ntsteps;
 
-  return (ntsteps);
+  return ntsteps;
 }
 
 static
@@ -399,7 +399,7 @@ int cdiInqContents(stream_t * streamptr)
         }
     }
 
-  return (status);
+  return status;
 }
 
 int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
@@ -522,7 +522,7 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
     default:
       {
         if ( CDI_Debug ) Message("%s support not compiled in!", strfiletype(filetype));
-        return (CDI_ELIBNAVAIL);
+        return CDI_ELIBNAVAIL;
       }
     }
 
@@ -534,27 +534,21 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
 
 int streamOpenID(const char *filename, char filemode, int filetype, int resH)
 {
-  int fileID = CDI_UNDEFID;
-  int status;
-
   if ( CDI_Debug )
     Message("Open %s mode %c file %s", strfiletype(filetype), filemode,
             filename?filename:"(NUL)");
 
-  if ( ! filename || filetype < 0 ) return (CDI_EINVAL);
+  if ( ! filename || filetype < 0 ) return CDI_EINVAL;
 
   stream_t *streamptr = stream_new_entry(resH);
   int streamID = CDI_ESYSTEM;
 
-  {
-    int (*streamOpenDelegate)(const char *filename, char filemode,
-                              int filetype, stream_t *streamptr, int recordBufIsToBeCreated)
-      = (int (*)(const char *, char, int, stream_t *, int))
-      namespaceSwitchGet(NSSWITCH_STREAM_OPEN_BACKEND).func;
-
-    fileID = streamOpenDelegate(filename, filemode, filetype, streamptr, 1);
-  }
+  int (*streamOpenDelegate)(const char *filename, char filemode,
+                            int filetype, stream_t *streamptr, int recordBufIsToBeCreated)
+    = (int (*)(const char *, char, int, stream_t *, int))
+    namespaceSwitchGet(NSSWITCH_STREAM_OPEN_BACKEND).func;
 
+  int fileID = streamOpenDelegate(filename, filemode, filetype, streamptr, 1);
   if ( fileID < 0 )
     {
       streamID = fileID;
@@ -562,7 +556,6 @@ int streamOpenID(const char *filename, char filemode, int filetype, int resH)
   else
     {
       streamID = streamptr->self;
-
       if ( streamID < 0 ) return CDI_ELIMIT;
 
       streamptr->filemode = filemode;
@@ -572,12 +565,12 @@ int streamOpenID(const char *filename, char filemode, int filetype, int resH)
       if ( filemode == 'r' )
         {
           int vlistID = vlistCreate();
-          if ( vlistID < 0 ) return(CDI_ELIMIT);
+          if ( vlistID < 0 ) return CDI_ELIMIT;
 
           cdiVlistMakeInternal(vlistID);
           streamptr->vlistID = vlistID;
           /* cdiReadByteorder(streamID); */
-          status = cdiInqContents(streamptr);
+          int status = cdiInqContents(streamptr);
           if ( status < 0 )
             {
               streamID = status;
@@ -619,7 +612,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
     Message("Open %s file (mode=%c); filename: %s", strfiletype(filetype), (int) *filemode, filename);
   if ( CDI_Debug ) printf("streamOpenA: %s\n", filename); // seg fault without this line on thunder/squall with "cdo cat x y"
 
-  if ( ! filename || ! filemode || filetype < 0 ) return (CDI_EINVAL);
+  if ( ! filename || ! filemode || filetype < 0 ) return CDI_EINVAL;
 
   {
     int (*streamOpenDelegate)(const char *filename, char filemode,
@@ -630,7 +623,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
     fileID = streamOpenDelegate(filename, 'r', filetype, streamptr, 1);
   }
 
-  if ( fileID == CDI_UNDEFID || fileID == CDI_ELIBNAVAIL || fileID == CDI_ESYSTEM ) return (fileID);
+  if ( fileID == CDI_UNDEFID || fileID == CDI_ELIBNAVAIL || fileID == CDI_ESYSTEM ) return fileID;
 
   streamID = streamptr->self;
 
@@ -642,7 +635,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
   cdiVlistMakeInternal(streamptr->vlistID);
   /* cdiReadByteorder(streamID); */
   status = cdiInqContents(streamptr);
-  if ( status < 0 ) return (status);
+  if ( status < 0 ) return status;
   vlistptr = vlist_to_pointer(streamptr->vlistID);
   vlistptr->ntsteps = (int)cdiInqTimeSize(streamID);
   if(!strcmp(filemode, "r")) cdiVlistMakeImmutable(streamptr->vlistID);
@@ -710,7 +703,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
     default:
       {
 	if ( CDI_Debug ) Message("%s support not compiled in!", strfiletype(filetype));
-	return (CDI_ELIBNAVAIL);
+	return CDI_ELIBNAVAIL;
       }
     }
 
@@ -719,7 +712,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
   else
     streamptr->fileID = fileID;
 
-  return (streamID);
+  return streamID;
 }
 
 /*
@@ -767,7 +760,7 @@ int streamOpenRead(const char *filename)
   int byteorder = 0;
   int filetype = cdiGetFiletype(filename, &byteorder);
 
-  if ( filetype < 0 ) return (filetype);
+  if ( filetype < 0 ) return filetype;
 
   int streamID = streamOpen(filename, "r", filetype);
 
@@ -777,7 +770,7 @@ int streamOpenRead(const char *filename)
       streamptr->byteorder = byteorder;
     }
 
-  return (streamID);
+  return streamID;
 }
 
 
@@ -788,7 +781,7 @@ int streamOpenAppend(const char *filename)
   int byteorder = 0;
   int filetype = cdiGetFiletype(filename, &byteorder);
 
-  if ( filetype < 0 ) return (filetype);
+  if ( filetype < 0 ) return filetype;
 
   int streamID = streamOpenA(filename, "a", filetype);
 
@@ -798,7 +791,7 @@ int streamOpenAppend(const char *filename)
       streamptr->byteorder = byteorder;
     }
 
-  return (streamID);
+  return streamID;
 }
 
 /*
@@ -845,7 +838,7 @@ int streamOpenWrite(const char *filename, int filetype)
 {
   cdiInitialize();
 
-  return (streamOpen(filename, "w", filetype));
+  return streamOpen(filename, "w", filetype);
 }
 
 static
@@ -1281,12 +1274,12 @@ int streamInqTimestep(int streamID, int tsID)
 	Error("Timestep undefined for fileID = %d", streamID);
       ptaxisCopy(taxisPtr(taxisID), &streamptr->tsteps[tsID].taxis);
 
-      return (nrecs);
+      return nrecs;
     }
 
   if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
     {
-      return (0);
+      return 0;
     }
 
   int filetype = streamptr->filetype;
@@ -1348,7 +1341,7 @@ int streamInqTimestep(int streamID, int tsID)
 
   ptaxisCopy(taxisPtr(taxisID), &streamptr->tsteps[tsID].taxis);
 
-  return (nrecs);
+  return nrecs;
 }
 
 #if 0
@@ -1452,7 +1445,7 @@ off_t streamNvals(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
-  return (streamptr->numvals);
+  return streamptr->numvals;
 }
 
 /*
@@ -1516,14 +1509,14 @@ The function @func{streamInqVlist} returns the variable list of a stream.
 int streamInqVlist(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  return (streamptr->vlistID);
+  return streamptr->vlistID;
 }
 
 
 void streamDefCompType(int streamID, int comptype)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  if (streamptr->comptype != comptype)
+  if ( streamptr->comptype != comptype )
     {
       streamptr->comptype = comptype;
       reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
@@ -1534,7 +1527,7 @@ void streamDefCompType(int streamID, int comptype)
 void streamDefCompLevel(int streamID, int complevel)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  if (streamptr->complevel != complevel)
+  if ( streamptr->complevel != complevel )
     {
       streamptr->complevel = complevel;
       reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
@@ -1545,23 +1538,20 @@ void streamDefCompLevel(int streamID, int complevel)
 int streamInqCompType(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  return (streamptr->comptype);
+  return streamptr->comptype;
 }
 
 
 int streamInqCompLevel(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
-  return (streamptr->complevel);
+  return streamptr->complevel;
 }
 
 int streamInqFileID(int streamID)
 {
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->fileID);
+  stream_t *streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+  return streamptr->fileID;
 }
 
 
@@ -1582,8 +1572,7 @@ void cdiDefAccesstype(int streamID, int type)
 int cdiInqAccesstype(int streamID)
 {
   stream_t *streamptr = (stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->accesstype);
+  return streamptr->accesstype;
 }
 
 static
diff --git a/libcdi/src/stream_cdf.c b/libcdi/src/stream_cdf.c
index 290dd84..90c5a15 100644
--- a/libcdi/src/stream_cdf.c
+++ b/libcdi/src/stream_cdf.c
@@ -34,13 +34,14 @@
 #include "cdf_int.h"
 #include "varscan.h"
 #include "vlist.h"
+#include "zaxis.h"
 
 //#define PROJECTION_TEST
 
 #undef  UNDEFID
 #define UNDEFID  CDI_UNDEFID
 
-#define  BNDS_NAME  "bnds"
+static const char bndsName[] = "bnds";
 
 #define  X_AXIS  1
 #define  Y_AXIS  2
@@ -89,6 +90,7 @@ typedef struct {
   int      zvarid;
   int      tvarid;
   int      psvarid;
+  int      p0varid;
   int      ncoordvars;
   int      coordvarids[MAX_COORDVARS];
   int      nauxvars;
@@ -164,33 +166,27 @@ int get_timeunit(size_t len, const char *ptu)
 static
 bool isTimeUnits(const char *timeunits)
 {
-  bool status = false;
-
-  if ( strncmp(timeunits, "sec",    3) == 0 ||
-       strncmp(timeunits, "minute", 6) == 0 ||
-       strncmp(timeunits, "hour",   4) == 0 ||
-       strncmp(timeunits, "day",    3) == 0 ||
-       strncmp(timeunits, "month",  5) == 0 ) status = true;
-
+  bool status = strncmp(timeunits, "sec",    3) == 0
+    || strncmp(timeunits, "minute", 6) == 0
+    || strncmp(timeunits, "hour",   4) == 0
+    || strncmp(timeunits, "day",    3) == 0
+    || strncmp(timeunits, "month",  5) == 0;
   return status;
 }
 
 static
 bool isTimeAxisUnits(const char *timeunits)
 {
-  char *ptu, *tu;
-  int timetype = -1;
-  int timeunit;
   bool status = false;
 
   size_t len = strlen(timeunits);
-  tu = (char *) Malloc((len+1)*sizeof(char));
+  char *tu = (char *) Malloc((len+1)*sizeof(char));
   memcpy(tu, timeunits, (len+1) * sizeof(char));
-  ptu = tu;
+  char *ptu = tu;
 
   for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
 
-  timeunit = get_timeunit(len, ptu);
+  int timeunit = get_timeunit(len, ptu);
   if ( timeunit != -1 )
     {
 
@@ -199,12 +195,10 @@ bool isTimeAxisUnits(const char *timeunits)
         {
           while ( isspace(*ptu) ) ptu++;
 
-          if ( memcmp(ptu, "as", 2) == 0 )
-            timetype = TAXIS_ABSOLUTE;
-          else if ( memcmp(ptu, "since", 5) == 0 )
-            timetype = TAXIS_RELATIVE;
+          int timetype = memcmp(ptu, "as", 2) == 0 ? TAXIS_ABSOLUTE :
+            memcmp(ptu, "since", 5) == 0 ? TAXIS_RELATIVE : -1;
 
-          if ( timetype != -1 ) status = true;
+          status = timetype != -1;
         }
     }
 
@@ -382,12 +376,8 @@ void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int
 
   if ( atttype != NC_CHAR )
     {
-      int *pintatt = NULL;
-
-      if ( (int)nc_attlen > attlen )
-        pintatt = (int *) Malloc(nc_attlen * sizeof (int));
-      else
-        pintatt = attint;
+      int *pintatt = (int)nc_attlen > attlen
+        ? (int *)(Malloc(nc_attlen * sizeof (int))) : attint;
 
       cdf_get_att_int(fileID, ncvarid, attname, pintatt);
 
@@ -496,10 +486,7 @@ int xtypeIsText(int xtype)
 static
 int xtypeIsFloat(int xtype)
 {
-  int isFloat = FALSE;
-
-  if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
-
+  int isFloat = xtype == NC_FLOAT || xtype == NC_DOUBLE;
   return isFloat;
 }
 
@@ -533,7 +520,6 @@ int cdfInqDatatype(int xtype, int lunsigned)
 
 void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int memtype  = MEMTYPE_DOUBLE;
   int vlistID1 = streamptr1->vlistID;
   int tsID     = streamptr1->curTsID;
   int vrecID   = streamptr1->tsteps[tsID].curRecID;
@@ -542,14 +528,11 @@ void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
   int gridID   = vlistInqVarGrid(vlistID1, ivarID);
   int datasize = gridInqSize(gridID);
   int datatype = vlistInqVarDatatype(vlistID1, ivarID);
+  int memtype  = datatype != DATATYPE_FLT32 ? MEMTYPE_DOUBLE : MEMTYPE_FLOAT;
 
-  if ( datatype == DATATYPE_FLT32 ) memtype = MEMTYPE_FLOAT;
-
-  void *data = NULL;
-  if ( memtype == MEMTYPE_DOUBLE )
-    data = Malloc((size_t)datasize*sizeof(double));
-  else
-    data = Malloc((size_t)datasize*sizeof(float));
+  void *data
+    = Malloc((size_t)datasize
+             * (memtype == MEMTYPE_DOUBLE ? sizeof(double) : sizeof(float)));
 
   int nmiss;
   cdf_read_record(streamptr1, memtype, data, &nmiss);
@@ -670,36 +653,43 @@ printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
 }
 
 static
-int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, char* taxis_name, taxis_t* taxis)
+int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *taxis_name, taxis_t* taxis)
 {
   int time_bndsid = -1;
   int dims[2];
-  char tmpstr[CDI_MAX_NAME];
 
   dims[0] = nctimedimid;
 
   /* fprintf(stderr, "time has bounds\n"); */
 
-  if ( nc_inq_dimid(fileID, BNDS_NAME, &dims[1]) != NC_NOERR )
-    cdf_def_dim(fileID, BNDS_NAME, 2, &dims[1]);
+  if ( nc_inq_dimid(fileID, bndsName, &dims[1]) != NC_NOERR )
+    cdf_def_dim(fileID, bndsName, 2, &dims[1]);
 
+  const char *bndsAttName, *bndsAttVal;
+  size_t bndsAttValLen;
+  char tmpstr[CDI_MAX_NAME];
   if ( taxis->climatology )
     {
-      strcpy(tmpstr, "climatology_");
-      strcat(tmpstr, BNDS_NAME);
-      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
-
-      cdf_put_att_text(fileID, nctimevarid, "climatology", strlen(tmpstr), tmpstr);
+      static const char climatology_bndsName[] = "climatology_bnds",
+        climatology_bndsAttName[] = "climatology";
+      bndsAttName = climatology_bndsAttName;
+      bndsAttValLen = sizeof (climatology_bndsName) - 1;
+      bndsAttVal = climatology_bndsName;
     }
   else
     {
-      strcpy(tmpstr, taxis_name);
-      strcat(tmpstr, "_");
-      strcat(tmpstr, BNDS_NAME);
-      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
-
-      cdf_put_att_text(fileID, nctimevarid, "bounds", strlen(tmpstr), tmpstr);
+      size_t taxisnameLen = strlen(taxis_name);
+      memcpy(tmpstr, taxis_name, taxisnameLen);
+      tmpstr[taxisnameLen] = '_';
+      memcpy(tmpstr + taxisnameLen + 1, bndsName, sizeof (bndsName));
+      size_t tmpstrLen = taxisnameLen + sizeof (bndsName);
+      static const char generic_bndsAttName[] = "bounds";
+      bndsAttName = generic_bndsAttName;
+      bndsAttValLen = tmpstrLen;
+      bndsAttVal = tmpstr;
     }
+  cdf_def_var(fileID, bndsAttVal, NC_DOUBLE, 2, dims, &time_bndsid);
+  cdf_put_att_text(fileID, nctimevarid, bndsAttName, bndsAttValLen, bndsAttVal);
 
   return (time_bndsid);
 }
@@ -720,8 +710,7 @@ void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
     }
   else
     {
-      int timeunit = taxis->unit;
-      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
+      int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR;
       int rdate    = taxis->rdate;
       int rtime    = taxis->rtime;
       if ( rdate == -1 )
@@ -758,27 +747,30 @@ void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
        timeunit == TUNIT_6HOURS  ||
        timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
 
-  sprintf(unitstr, "%s", tunitNamePtr(timeunit));
+  strcpy(unitstr, tunitNamePtr(timeunit));
 }
 
 static
 void cdfDefCalendar(int fileID, int ncvarid, int calendar)
 {
-  size_t len;
-  char calstr[80];
-
-  calstr[0] = 0;
-
-  if      ( calendar == CALENDAR_STANDARD )  strcpy(calstr, "standard");
-  else if ( calendar == CALENDAR_PROLEPTIC ) strcpy(calstr, "proleptic_gregorian");
-  else if ( calendar == CALENDAR_NONE )      strcpy(calstr, "none");
-  else if ( calendar == CALENDAR_360DAYS )   strcpy(calstr, "360_day");
-  else if ( calendar == CALENDAR_365DAYS )   strcpy(calstr, "365_day");
-  else if ( calendar == CALENDAR_366DAYS )   strcpy(calstr, "366_day");
-
-  len = strlen(calstr);
+  static const struct { int calCode; const char *calStr; } calTab[] = {
+    { CALENDAR_STANDARD, "standard" },
+    { CALENDAR_PROLEPTIC, "proleptic_gregorian" },
+    { CALENDAR_NONE, "none" },
+    { CALENDAR_360DAYS, "360_day" },
+    { CALENDAR_365DAYS, "365_day" },
+    { CALENDAR_366DAYS, "366_day" },
+  };
+  enum { calTabSize = sizeof calTab / sizeof calTab[0] };
 
-  if ( len ) cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
+  for (size_t i = 0; i < calTabSize; ++i)
+    if (calTab[i].calCode == calendar)
+      {
+        const char *calstr = calTab[i].calStr;
+        size_t len = strlen(calstr);
+        cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
+        break;
+      }
 }
 
 
@@ -787,10 +779,7 @@ void cdfDefTime(stream_t* streamptr)
   int time_varid;
   int time_dimid;
   int time_bndsid = -1;
-  char unitstr[CDI_MAX_NAME];
-  char tmpstr[CDI_MAX_NAME];
-  char default_name[] = "time";
-  char* taxis_name = default_name;
+  static const char default_name[] = "time";
 
   if ( streamptr->basetime.ncvarid != UNDEFID ) return;
 
@@ -801,7 +790,7 @@ void cdfDefTime(stream_t* streamptr)
 
   taxis_t *taxis = &streamptr->tsteps[0].taxis;
 
-  if ( taxis->name && taxis->name[0] ) taxis_name = taxis->name;
+  const char *taxis_name = (taxis->name && taxis->name[0]) ? taxis->name : default_name ;
 
   cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
   streamptr->basetime.ncdimid = time_dimid;
@@ -810,8 +799,10 @@ void cdfDefTime(stream_t* streamptr)
 
   streamptr->basetime.ncvarid = time_varid;
 
-  strcpy(tmpstr, "time");
-  cdf_put_att_text(fileID, time_varid, "standard_name", strlen(tmpstr), tmpstr);
+  {
+    static const char timeStr[] = "time";
+    cdf_put_att_text(fileID, time_varid, "standard_name", sizeof(timeStr) - 1, timeStr);
+  }
 
   if ( taxis->longname && taxis->longname[0] )
     cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname);
@@ -822,17 +813,19 @@ void cdfDefTime(stream_t* streamptr)
       streamptr->basetime.ncvarboundsid = time_bndsid;
     }
 
-  cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
-
-  size_t len = strlen(unitstr);
-  if ( len )
-    {
-      cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
-      /*
-      if ( taxis->has_bounds )
-        cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
-      */
-    }
+  {
+    char unitstr[CDI_MAX_NAME];
+    cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
+    size_t len = strlen(unitstr);
+    if ( len )
+      {
+        cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
+        /*
+          if ( taxis->has_bounds )
+          cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
+        */
+      }
+  }
 
   if ( taxis->calendar != -1 )
     {
@@ -851,16 +844,23 @@ void cdfDefTime(stream_t* streamptr)
 
       streamptr->basetime.leadtimeid = leadtimeid;
 
-      strcpy(tmpstr, "forecast_period");
-      cdf_put_att_text(fileID, leadtimeid, "standard_name", strlen(tmpstr), tmpstr);
-
-      strcpy(tmpstr, "Time elapsed since the start of the forecast");
-      cdf_put_att_text(fileID, leadtimeid, "long_name", strlen(tmpstr), tmpstr);
+      {
+        static const char stdname[] = "forecast_period";
+        cdf_put_att_text(fileID, leadtimeid, "standard_name", sizeof(stdname) - 1, stdname);
+      }
 
-      cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);
+      {
+        static const char lname[] = "Time elapsed since the start of the forecast";
+        cdf_put_att_text(fileID, leadtimeid, "long_name", sizeof(lname) - 1, lname);
+      }
 
-      len = strlen(unitstr);
-      if ( len ) cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
+      {
+          char unitstr[CDI_MAX_NAME];
+          cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);
+          size_t len = strlen(unitstr);
+          if ( len )
+            cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
+      }
     }
 
   cdf_put_att_text(fileID, time_varid, "axis", 1, "T");
@@ -881,7 +881,7 @@ void cdfDefTimestep(stream_t *streamptr, int tsID)
 static
 void cdfDefComplex(stream_t *streamptr, int gridID)
 {
-  char axisname[] = "nc2";
+  static const char axisname[] = "nc2";
   int dimID = UNDEFID;
   int vlistID = streamptr->vlistID;
   int fileID  = streamptr->fileID;
@@ -918,19 +918,14 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
   streamptr->xdimID[gridindex] = dimID;
 }
 
-
-static
-void cdfDefSP(stream_t *streamptr, int gridID)
+static void
+cdfDefSPorFC(stream_t *streamptr, int gridID,
+             char *restrict axisname, int gridRefType)
 {
-  /*
-  char longname[] = "Spherical harmonic coefficient";
-  */
-  char axisname[5] = "nspX";
   int index, iz = 0;
   int dimID = UNDEFID;
 
   int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
 
   int ngrids = vlistNgrids(vlistID);
 
@@ -942,7 +937,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
         {
           int gridID0 = vlistGrid(vlistID, index);
           int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_SPECTRAL )
+          if ( gridtype0 == gridRefType )
             {
               size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
               if ( dimlen == dimlen0 )
@@ -958,6 +953,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
+      int fileID  = streamptr->fileID;
       if ( iz == 0 ) axisname[3] = '\0';
       else           sprintf(&axisname[3], "%1d", iz+1);
 
@@ -973,76 +969,94 @@ void cdfDefSP(stream_t *streamptr, int gridID)
   streamptr->ydimID[gridindex] = dimID;
 }
 
+static
+void cdfDefSP(stream_t *streamptr, int gridID)
+{
+  /*
+  char longname[] = "Spherical harmonic coefficient";
+  */
+  char axisname[5] = "nspX";
+  cdfDefSPorFC(streamptr, gridID, axisname, GRID_SPECTRAL);
+}
+
 
 static
 void cdfDefFC(stream_t *streamptr, int gridID)
 {
   char axisname[5] = "nfcX";
-  int index, iz = 0;
-  int dimID = UNDEFID;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  int ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqSize(gridID)/2;
-
-  for ( index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->ydimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_FOURIER )
-            {
-              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
-              if ( dimlen == dimlen0 )
-                {
-                  dimID = streamptr->ydimID[index];
-                  break;
-                }
-              else
-                iz++;
-            }
-        }
-    }
-
-  if ( dimID == UNDEFID )
-    {
-      if ( iz == 0 ) axisname[3] = '\0';
-      else           sprintf(&axisname[3], "%1d", iz+1);
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  streamptr->ydimID[gridindex] = dimID;
+  cdfDefSPorFC(streamptr, gridID, axisname, GRID_FOURIER);
 }
 
-struct cdfDefTrajLatLonInqs {
-  int (*gridInqDimSize)(int gridID);
-  void (*gridInqDimName)(int gridID, char *dimname);
-  void (*gridInqDimStdname)(int gridID, char *dimstdname);
-  void (*gridInqDimLongname)(int gridID, char *dimlongname);
-  void (*gridInqDimUnits)(int gridID, char *dimunits);
+static const struct cdfDefGridAxisInqs {
+  int (*axisSize)(int gridID);
+  void (*axisName)(int gridID, char *dimname);
+  const char *(*axisNamePtr)(int gridID);
+  void (*axisStdname)(int gridID, char *dimstdname);
+  void (*axisLongname)(int gridID, char *dimlongname);
+  void (*axisUnits)(int gridID, char *dimunits);
+  double (*axisVal)(int gridID, int index);
+  const double *(*axisValsPtr)(int gridID);
+  const double *(*axisBoundsPtr)(int gridID);
+} gridInqsX = {
+  .axisSize = gridInqXsize,
+  .axisName = gridInqXname,
+  .axisNamePtr = gridInqXnamePtr,
+  .axisStdname = gridInqXstdname,
+  .axisLongname = gridInqXlongname,
+  .axisUnits = gridInqXunits,
+  .axisVal = gridInqXval,
+  .axisValsPtr = gridInqXvalsPtr,
+  .axisBoundsPtr = gridInqXboundsPtr,
+}, gridInqsY = {
+  .axisSize = gridInqYsize,
+  .axisName = gridInqYname,
+  .axisNamePtr = gridInqYnamePtr,
+  .axisStdname = gridInqYstdname,
+  .axisLongname = gridInqYlongname,
+  .axisUnits = gridInqYunits,
+  .axisVal = gridInqYval,
+  .axisValsPtr = gridInqYvalsPtr,
+  .axisBoundsPtr = gridInqYboundsPtr,
+}, gridInqsZ = {
+  .axisStdname = zaxisInqStdname,
+  .axisLongname = zaxisInqLongname,
+  .axisUnits = zaxisInqUnits,
 };
 
+static void
+cdfPutGridStdAtts(int fileID, int ncvarid,
+                  int gridID, const struct cdfDefGridAxisInqs *inqs)
+{
+  size_t len;
+  {
+    char stdname[CDI_MAX_NAME];
+    inqs->axisStdname(gridID, stdname);
+    if ( (len = strlen(stdname)) )
+      cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
+  }
+  {
+    char longname[CDI_MAX_NAME];
+    inqs->axisLongname(gridID, longname);
+    if ( (len = strlen(longname)) )
+      cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
+  }
+  {
+    char units[CDI_MAX_NAME];
+    inqs->axisUnits(gridID, units);
+    if ( (len = strlen(units)) )
+      cdf_put_att_text(fileID, ncvarid, "units", len, units);
+  }
+}
 
 static void
 cdfDefTrajLatLon(stream_t *streamptr, int gridID,
-                 const struct cdfDefTrajLatLonInqs *inqs,
+                 const struct cdfDefGridAxisInqs *inqs,
                  int *dimID, const char *sizeName)
 {
   nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
 
   int vlistID = streamptr->vlistID;
-  int dimlen = inqs->gridInqDimSize(gridID);
+  int dimlen = inqs->axisSize(gridID);
   if ( dimlen != 1 )
     Error("%s isn't 1 for %s grid!", sizeName, gridNamePtr(gridInqType(gridID)));
 
@@ -1051,34 +1065,13 @@ cdfDefTrajLatLon(stream_t *streamptr, int gridID,
 
   if ( ncvarid == UNDEFID )
     {
-      size_t len;
       int dimNcID = streamptr->basetime.ncvarid;
       int fileID  = streamptr->fileID;
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      {
-        char axisname[CDI_MAX_NAME];
-        inqs->gridInqDimName(gridID, axisname);
-        cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
-      }
-      {
-        char stdname[CDI_MAX_NAME];
-        inqs->gridInqDimStdname(gridID, stdname);
-        if ( (len = strlen(stdname)) )
-          cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-      }
-      {
-        char longname[CDI_MAX_NAME];
-        inqs->gridInqDimLongname(gridID, longname);
-        if ( (len = strlen(longname)) )
-          cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-      }
-      {
-        char units[CDI_MAX_NAME];
-        inqs->gridInqDimUnits(gridID, units);
-        if ( (len = strlen(units)) )
-          cdf_put_att_text(fileID, ncvarid, "units", len, units);
-      }
+      const char *axisname = inqs->axisNamePtr(gridID);
+      cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
+      cdfPutGridStdAtts(fileID, ncvarid, gridID, inqs);
       cdf_enddef(fileID);
       streamptr->ncmode = 2;
     }
@@ -1089,271 +1082,171 @@ cdfDefTrajLatLon(stream_t *streamptr, int gridID,
 static
 void cdfDefTrajLon(stream_t *streamptr, int gridID)
 {
-  static const struct cdfDefTrajLatLonInqs inqs =
-    { .gridInqDimSize = gridInqXsize,
-      .gridInqDimName = gridInqXname,
-      .gridInqDimStdname = gridInqXstdname,
-      .gridInqDimLongname = gridInqXlongname,
-      .gridInqDimUnits = gridInqXunits
-    };
-  cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->xdimID, "Xsize");
+  cdfDefTrajLatLon(streamptr, gridID, &gridInqsX, streamptr->xdimID, "Xsize");
 }
 
 
 static
 void cdfDefTrajLat(stream_t *streamptr, int gridID)
 {
-  static const struct cdfDefTrajLatLonInqs inqs =
-    { .gridInqDimSize = gridInqYsize,
-      .gridInqDimName = gridInqYname,
-      .gridInqDimStdname = gridInqYstdname,
-      .gridInqDimLongname = gridInqYlongname,
-      gridInqYunits
-  };
-  cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->ydimID, "Ysize");
+  cdfDefTrajLatLon(streamptr, gridID, &gridInqsY, streamptr->ydimID, "Ysize");
 }
 
+static
+int checkDimName(int fileID, size_t dimlen, char *dimname)
+{
+  /* check whether the dimenion name is already defined with the same length */
+  unsigned iz = 0;
+  int dimid = UNDEFID;
+  char name[CDI_MAX_NAME];
+
+  size_t len = strlen(dimname);
+  memcpy(name, dimname, len + 1);
+
+  do
+    {
+      if ( iz ) sprintf(name + len, "_%u", iz+1);
+
+      int dimid0, status = nc_inq_dimid(fileID, name, &dimid0);
+      if ( status != NC_NOERR )
+        break;
+      size_t dimlen0;
+      cdf_inq_dimlen(fileID, dimid0, &dimlen0);
+      if ( dimlen0 == dimlen )
+        {
+          dimid = dimid0;
+          break;
+        }
+      iz++;
+    }
+  while ( iz <= 99 );
+
+
+  if ( iz ) sprintf(dimname + len, "_%u", iz+1);
+
+  return dimid;
+}
 
 static
-int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode)
+void checkGridName(char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode)
 {
-  int index;
-  int gridID0;
   int ncdimid;
-  char axisname0[CDI_MAX_NAME];
   char axisname2[CDI_MAX_NAME];
-  int status;
 
   /* check that the name is not already defined */
-  int checkname = TRUE;
   unsigned iz = 0;
 
+  size_t axisnameLen = strlen(axisname);
+  memcpy(axisname2, axisname, axisnameLen + 1);
   do
     {
-      strcpy(axisname2, axisname);
-      if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%u", iz+1);
+      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
 
-      //status = nc_inq_varid(fileID, axisname2, &ncvarid);
-      if ( type == 'V' ) /* type Var oder Dim */
-        status = nc_inq_varid(fileID, axisname2, &ncdimid);
-      else
-        status = nc_inq_dimid(fileID, axisname2, &ncdimid);
+      int status = nc_inq_varid(fileID, axisname2, &ncdimid);
 
       if ( status != NC_NOERR )
         {
           if ( iz )
             {
               /* check that the name does not exist for other grids */
-              for ( index = 0; index < ngrids; index++ )
+              for ( int index = 0; index < ngrids; index++ )
                 {
-                  gridID0 = vlistGrid(vlistID, index);
+                  int gridID0 = vlistGrid(vlistID, index);
                   if ( gridID != gridID0 )
                     {
-                      if ( mode == 'X' ) /* mode X or Y */
-                        gridInqXname(gridID0, axisname0);
-                      else
-                        gridInqYname(gridID0, axisname0);
-
-                      if ( strcmp(axisname0, axisname2) == 0 ) break;
+                       /* mode X or Y */
+                      const char *(*query)(int)
+                        = mode == 'X' ? gridInqXnamePtr : gridInqYnamePtr;
+                      const char *axisname0 = query(gridID0);
+                      if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix;
                     }
                 }
-              if ( index == ngrids ) checkname = FALSE;
-            }
-          else
-            {
-              checkname = FALSE;
             }
+          break;
         }
-
-      if ( checkname ) iz++;
+      nextSuffix:
+      ++iz;
     }
-  while (checkname && iz <= 99);
-
+  while ( iz <= 99 );
 
-  if ( iz ) sprintf(&axisname[strlen(axisname)], "_%u", iz+1);
 
-  return (int)iz;
+  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
 }
 
 static
-void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
+int checkZaxisName(char *axisname, int fileID, int vlistID, int zaxisID, int nzaxis)
 {
-  char units[CDI_MAX_NAME];
-  char longname[CDI_MAX_NAME];
-  char stdname[CDI_MAX_NAME];
-  char axisname[CDI_MAX_NAME];
-  int index;
-  /*  int index2; */
-  int dimID = UNDEFID;
-  int dimIDs[2];
-  int ngrids = 0;
-  size_t len;
-  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvdimID = UNDEFID;
-  nc_type xtype = NC_DOUBLE;
-
-  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  if ( ndims ) ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqXsize(gridID);
-  int gridindex = vlistGridIndex(vlistID, gridID);
-
-  gridInqXname(gridID, axisname);
-  if ( axisname[0] == 0 ) Error("axis name undefined!");
-
-  gridInqXlongname(gridID, longname);
-  gridInqXstdname(gridID, stdname);
-  gridInqXunits(gridID, units);
+  char axisname2[CDI_MAX_NAME];
 
-  for ( index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->xdimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_GAUSSIAN    ||
-               gridtype0 == GRID_LONLAT      ||
-               gridtype0 == GRID_CURVILINEAR ||
-               gridtype0 == GRID_GENERIC )
-            {
-              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
-              if ( dimlen == dimlen0 )
-                if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
-                  {
-                    dimID = streamptr->xdimID[index];
-                    break;
-                  }
-              /*
-              for ( index2 = 0; index2 < index; index2++ )
-                if ( streamptr->xdimID[index] == streamptr->xdimID[index2] )
-                  break;
-              if ( index2 == index ) iz++;
-              */
-            }
-        }
-    }
+  /* check that the name is not already defined */
+  unsigned iz = 0;
 
-  if ( dimID == UNDEFID )
+  size_t axisnameLen = strlen(axisname);
+  memcpy(axisname2, axisname, axisnameLen + 1);
+  do
     {
-      int status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'X');
-      if ( status == 0 && ndims )
-        status = checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
 
-      if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      int ncdimid, status = nc_inq_varid(fileID, axisname2, &ncdimid);
 
-      int gen_bounds = FALSE;
-      int grid_is_cyclic = gridIsCircular(gridID);
-      const double *pvals = gridInqXvalsPtr(gridID);
-      double *pbounds = NULL;
-      if ( pvals )
+      if ( status != NC_NOERR )
         {
-          cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
-
-          if ( (len = strlen(stdname)) )
-            cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-          if ( (len = strlen(longname)) )
-            cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-          if ( (len = strlen(units)) )
-            cdf_put_att_text(fileID, ncvarid, "units", len, units);
-
-          cdf_put_att_text(fileID, ncvarid, "axis", 1, "X");
-
-          if ( gridInqXboundsPtr(gridID) )
-            pbounds = (double*) gridInqXboundsPtr(gridID);
-
-          if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
+          if ( iz )
             {
-              gen_bounds = TRUE;
-              pbounds = (double*) malloc(2*dimlen*sizeof(double));
-              for ( size_t i = 0; i < dimlen-1; ++i )
+              /* check that the name does not exist for other zaxes */
+              for ( int index = 0; index < nzaxis; index++ )
                 {
-                  pbounds[i*2+1]   = (pvals[i] + pvals[i+1])/2;
-                  pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
+                  int zaxisID0 = vlistZaxis(vlistID, index);
+                  if ( zaxisID != zaxisID0 )
+                    {
+                      const char *axisname0 = zaxisInqNamePtr(zaxisID0);
+                      if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix;
+                    }
                 }
-              pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)/2;
-              pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)/2;
             }
-          if ( pbounds )
-            {
-              size_t nvertex = 2;
-              if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-                cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
-            }
-          if ( pbounds && nvdimID != UNDEFID )
-            {
-              strcat(axisname, "_");
-              strcat(axisname, BNDS_NAME);
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
-              cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
-            }
-          /*
-          if ( gridIsRotated(gridID) )
-            {
-              double north_pole = gridInqXpole(gridID);
-              cdf_put_att_double(fileID, ncvarid, "north_pole", NC_DOUBLE, 1, &north_pole);
-            }
-          */
+          break;
         }
+      nextSuffix:
+      ++iz;
+    }
+  while (iz <= 99);
 
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
 
-      if ( ncvarid  != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
-      if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
-      if ( gen_bounds ) Free(pbounds);
+  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
 
-      if ( ndims == 0 ) streamptr->ncxvarID[gridindex] = ncvarid;
-    }
-
-  streamptr->xdimID[gridindex] = dimID;
+  return (int)iz;
 }
 
-static
-void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
+static void
+cdfDefAxisCommon(stream_t *streamptr, int gridID, int ndims,
+                 const struct cdfDefGridAxisInqs *gridAxisInq,
+                 int *axisDimIDs, int dimKey, char axisLetter,
+                 void (*finishCyclicBounds)(double *pbounds, size_t dimlen,
+                                            const double *pvals),
+                 int *ncAxisVarIDs)
 {
-  char units[CDI_MAX_NAME];
-  char longname[CDI_MAX_NAME];
-  char stdname[CDI_MAX_NAME];
-  char axisname[CDI_MAX_NAME];
-  int index;
-  /*  int index2; */
   int dimID = UNDEFID;
-  int dimIDs[2];
   int ngrids = 0;
-  size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
   int nvdimID = UNDEFID;
-  nc_type xtype = NC_DOUBLE;
-
-  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
+  nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
 
   int vlistID = streamptr->vlistID;
   int fileID  = streamptr->fileID;
 
   if ( ndims ) ngrids = vlistNgrids(vlistID);
 
-  size_t dimlen = (size_t)gridInqYsize(gridID);
+  size_t dimlen = (size_t)gridAxisInq->axisSize(gridID);
   int gridindex = vlistGridIndex(vlistID, gridID);
 
-  gridInqYname(gridID, axisname);
-  if ( axisname[0] == 0 ) Error("axis name undefined!");
+  const char *axisname = gridAxisInq->axisNamePtr(gridID);
+  size_t axisnameLen = strlen(axisname);
 
-  gridInqYlongname(gridID, longname);
-  gridInqYstdname(gridID, stdname);
-  gridInqYunits(gridID, units);
+  if ( axisname[0] == 0 ) Error("axis name undefined!");
 
-  for ( index = 0; index < ngrids; index++ )
+  for ( int index = 0; index < ngrids; index++ )
     {
-      if ( streamptr->ydimID[index] != UNDEFID )
+      if ( axisDimIDs[index] != UNDEFID )
         {
           int gridID0 = vlistGrid(vlistID, index);
           int gridtype0 = gridInqType(gridID0);
@@ -1362,89 +1255,91 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              size_t dimlen0 = (size_t)gridInqYsize(gridID0);
+              size_t dimlen0 = (size_t)gridAxisInq->axisSize(gridID0);
               if ( dimlen == dimlen0 )
-                if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
+                {
+                  double (*inqVal)(int gridID, int index)
+                    = gridAxisInq->axisVal;
+                  if ( IS_EQUAL(inqVal(gridID0, 0), inqVal(gridID, 0)) &&
+                       IS_EQUAL(inqVal(gridID0, (int)dimlen-1), inqVal(gridID, (int)dimlen-1)) )
                   {
-                    dimID = streamptr->ydimID[index];
+                    dimID = axisDimIDs[index];
                     break;
                   }
-              /*
-              for ( index2 = 0; index2 < index; index2++ )
-                if ( streamptr->ydimID[index] == streamptr->ydimID[index2] )
-                  break;
-              if ( index2 == index ) iz++;
-              */
+                }
             }
         }
     }
 
   if ( dimID == UNDEFID )
     {
-      int status;
-      status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'Y');
-      if ( status == 0 && ndims )
-        status = checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'Y');
+      const double *pvals = gridAxisInq->axisValsPtr(gridID);
+
+      /* enough to append _ plus up to 100 decimal and trailing \0 */
+      char extendedAxisname[axisnameLen + 4 + 1];
+      memcpy(extendedAxisname, axisname, axisnameLen + 1);
+      checkGridName(extendedAxisname, fileID, vlistID, gridID, ngrids, axisLetter);
+      size_t extendedAxisnameLen
+        = axisnameLen + strlen(extendedAxisname + axisnameLen);
 
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      if ( ndims )
+        {
+          char dimname[CDI_MAX_NAME+3];
+          dimname[0] = 0;
+
+          if ( pvals == NULL )
+            cdiGridInqString(gridID, dimKey, CDI_MAX_NAME, dimname);
+
+          if ( dimname[0] == 0 ) strcpy(dimname, extendedAxisname);
+          dimID = checkDimName(fileID, dimlen, dimname);
+
+          if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
+        }
 
-      int gen_bounds = FALSE;
+      bool gen_bounds = false;
       int grid_is_cyclic = gridIsCircular(gridID);
-      const double *pvals = gridInqYvalsPtr(gridID);
       double *pbounds = NULL;
       if ( pvals )
         {
-          cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
+          cdf_def_var(fileID, extendedAxisname, xtype, ndims, &dimID, &ncvarid);
 
-          if ( (len = strlen(stdname)) )
-            cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-          if ( (len = strlen(longname)) )
-            cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-          if ( (len = strlen(units)) )
-            cdf_put_att_text(fileID, ncvarid, "units", len, units);
-
-          cdf_put_att_text(fileID, ncvarid, "axis", 1, "Y");
+          cdfPutGridStdAtts(fileID, ncvarid, gridID, gridAxisInq);
+          {
+            char axisStr[2] = { axisLetter, '\0' };
+            cdf_put_att_text(fileID, ncvarid, "axis", 1, axisStr);
+          }
 
-          if ( gridInqYboundsPtr(gridID) )
-            pbounds = (double*) gridInqYboundsPtr(gridID);
+          pbounds = (double *)gridAxisInq->axisBoundsPtr(gridID);
 
           if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
             {
-              gen_bounds = TRUE;
-              pbounds = (double*) malloc(2*dimlen*sizeof(double));
+              gen_bounds = true;
+              pbounds = (double*) Malloc(2*dimlen*sizeof(double));
               for ( size_t i = 0; i < dimlen-1; ++i )
                 {
                   pbounds[i*2+1]   = (pvals[i] + pvals[i+1])/2;
                   pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
                 }
-              pbounds[0] = (pvals[0] < 0) ? -90 : 90;
-              pbounds[2*dimlen-1] = (pvals[dimlen-1] < 0) ? -90 : 90;
+              finishCyclicBounds(pbounds, dimlen, pvals);
             }
           if ( pbounds )
             {
               size_t nvertex = 2;
-              if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-                cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+              if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+                cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
             }
           if ( pbounds && nvdimID != UNDEFID )
             {
-              strcat(axisname, "_");
-              strcat(axisname, BNDS_NAME);
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
-              cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
-            }
-          /*
-          if ( gridIsRotated(gridID) )
-            {
-              double north_pole = gridInqYpole(gridID);
-              cdf_put_att_double(fileID, ncvarid, "north_pole", NC_DOUBLE, 1, &north_pole);
+              char boundsname[extendedAxisnameLen + 1 + sizeof (bndsName)];
+              memcpy(boundsname, axisname, extendedAxisnameLen);
+              boundsname[extendedAxisnameLen] = '_';
+              memcpy(boundsname + extendedAxisnameLen + 1, bndsName, sizeof bndsName);
+              int dimIDs[2] = { dimID, nvdimID };
+              cdf_def_var(fileID, boundsname, xtype, 2, dimIDs, &ncbvarid);
+              cdf_put_att_text(fileID, ncvarid, "bounds", extendedAxisnameLen + sizeof (bndsName), boundsname);
             }
-          */
         }
 
       cdf_enddef(fileID);
@@ -1454,10 +1349,40 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
       if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
       if ( gen_bounds ) Free(pbounds);
 
-      if ( ndims == 0 ) streamptr->ncyvarID[gridindex] = ncvarid;
+      if ( ndims == 0 ) ncAxisVarIDs[gridindex] = ncvarid;
     }
 
-  streamptr->ydimID[gridindex] = dimID;
+  axisDimIDs[gridindex] = dimID;
+}
+
+static void
+finishCyclicXBounds(double *pbounds, size_t dimlen, const double *pvals)
+{
+  pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)*0.5;
+  pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)*0.5;
+}
+
+static
+void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
+{
+  cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsX, streamptr->xdimID,
+                   CDI_GRID_XDIMNAME, 'X', finishCyclicXBounds,
+                   streamptr->ncxvarID);
+}
+
+static void
+finishCyclicYBounds(double *pbounds, size_t dimlen, const double *pvals)
+{
+  pbounds[0] = copysign(90.0, pvals[0]);
+  pbounds[2*dimlen-1] = copysign(90.0, pvals[dimlen-1]);
+}
+
+static
+void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
+{
+  cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsY, streamptr->ydimID,
+                   CDI_GRID_YDIMNAME, 'Y', finishCyclicYBounds,
+                   streamptr->ncyvarID);
 }
 
 static
@@ -1472,76 +1397,43 @@ void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int co
 #endif
 }
 
-
 static
 void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 {
-  char xunits[CDI_MAX_NAME];
-  char xlongname[CDI_MAX_NAME];
-  char xstdname[CDI_MAX_NAME];
-  char yunits[CDI_MAX_NAME];
-  char ylongname[CDI_MAX_NAME];
-  char ystdname[CDI_MAX_NAME];
-  char xaxisname[CDI_MAX_NAME];
-  char yaxisname[CDI_MAX_NAME];
-  char xdimname[4] = "x";
-  char ydimname[4] = "y";
-  int index;
   int xdimID = UNDEFID;
   int ydimID = UNDEFID;
-  int dimIDs[3];
-  size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  int nvdimID = UNDEFID;
-  nc_type xtype = NC_DOUBLE;
-
-  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
+  nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
 
   int vlistID = streamptr->vlistID;
   int fileID  = streamptr->fileID;
 
   int ngrids = vlistNgrids(vlistID);
 
+  size_t dimlen = (size_t)gridInqSize(gridID);
   size_t xdimlen = (size_t)gridInqXsize(gridID);
   size_t ydimlen = (size_t)gridInqYsize(gridID);
   int gridindex = vlistGridIndex(vlistID, gridID);
 
-  gridInqXname(gridID, xaxisname);
-  gridInqXlongname(gridID, xlongname);
-  gridInqXstdname(gridID, xstdname);
-  gridInqXunits(gridID, xunits);
-  gridInqYname(gridID, yaxisname);
-  gridInqYlongname(gridID, ylongname);
-  gridInqYstdname(gridID, ystdname);
-  gridInqYunits(gridID, yunits);
-
-  for ( index = 0; index < ngrids; index++ )
+  for ( int index = 0; index < ngrids; index++ )
     {
       if ( streamptr->xdimID[index] != UNDEFID )
         {
           int gridID0 = vlistGrid(vlistID, index);
           int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_GAUSSIAN    ||
-               gridtype0 == GRID_LONLAT      ||
-               gridtype0 == GRID_CURVILINEAR ||
-               gridtype0 == GRID_GENERIC )
+          if ( gridtype0 == GRID_CURVILINEAR )
             {
-              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
-              if ( xdimlen == dimlen0 )
+              size_t dimlen0 = (size_t)gridInqSize(gridID0);
+              if ( dimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)xdimlen-1), gridInqXval(gridID, (int)xdimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
+                     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
                   {
                     xdimID = streamptr->xdimID[index];
-                    ncxvarid = streamptr->ncxvarID[index];
-                    break;
-                  }
-              dimlen0 = (size_t)gridInqYsize(gridID0);
-              if ( ydimlen == dimlen0 )
-                if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, (int)xdimlen-1), gridInqYval(gridID, (int)xdimlen-1)) )
-                  {
                     ydimID = streamptr->ydimID[index];
+                    ncxvarid = streamptr->ncxvarID[index];
                     ncyvarid = streamptr->ncyvarID[index];
                     break;
                   }
@@ -1551,81 +1443,90 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 
   if ( xdimID == UNDEFID || ydimID == UNDEFID )
     {
-      checkGridName('V', xaxisname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('V', yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
-      checkGridName('D', xdimname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('D', ydimname, fileID, vlistID, gridID, ngrids, 'Y');
-
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+      {
+        char xdimname[CDI_MAX_NAME+3];
+        xdimname[0] = 0;
+        cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname);
+        if ( xdimname[0] == 0 ) { xdimname[0] = 'x'; xdimname[1] = 0; }
+        xdimID = checkDimName(fileID, xdimlen, xdimname);
+        if ( xdimID == UNDEFID ) cdf_def_dim(fileID, xdimname, xdimlen, &xdimID);
+      }
+      {
+        char ydimname[CDI_MAX_NAME+3];
+        ydimname[0] = 0;
+        cdiGridInqString(gridID, CDI_GRID_YDIMNAME, CDI_MAX_NAME, ydimname);
+        if ( ydimname[0] == 0 ) { ydimname[0] = 'y'; ydimname[1] = 0; }
+        ydimID = checkDimName(fileID, ydimlen, ydimname);
+        if ( ydimID == UNDEFID ) cdf_def_dim(fileID, ydimname, ydimlen, &ydimID);
+      }
 
-      cdf_def_dim(fileID, xdimname, xdimlen, &xdimID);
-      cdf_def_dim(fileID, ydimname, ydimlen, &ydimID);
-
+      int nvdimID = UNDEFID;
+      int dimIDs[3];
       if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
         {
+          char vdimname[CDI_MAX_NAME+3];
+          vdimname[0] = 0;
+          cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname);
+          if ( vdimname[0] == 0 ) strcpy(vdimname, "nv4");
           size_t nvertex = 4;
-          if ( nc_inq_dimid(fileID, "nv4", &nvdimID) != NC_NOERR )
-            cdf_def_dim(fileID, "nv4", nvertex, &nvdimID);
+          nvdimID = checkDimName(fileID, nvertex, vdimname);
+          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
         }
 
       dimIDs[0] = ydimID;
       dimIDs[1] = xdimID;
+      dimIDs[2] = nvdimID;
 
       if ( gridInqXvalsPtr(gridID) )
         {
+          char xaxisname[CDI_MAX_NAME];
+          gridInqXname(gridID, xaxisname);
+          checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X');
+
           cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid);
           cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(xstdname)) )
-            cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
-          if ( (len = strlen(xlongname)) )
-            cdf_put_att_text(fileID, ncxvarid, "long_name", len, xlongname);
-          if ( (len = strlen(xunits)) )
-            cdf_put_att_text(fileID, ncxvarid, "units", len, xunits);
+          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
 
           /* attribute for Panoply */
           cdf_put_att_text(fileID, ncxvarid, "_CoordinateAxisType", 3, "Lon");
 
           if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              strcat(xaxisname, "_");
-              strcat(xaxisname, BNDS_NAME);
-              dimIDs[0] = ydimID;
-              dimIDs[1] = xdimID;
-              dimIDs[2] = nvdimID;
+              size_t xaxisnameLen = strlen(xaxisname);
+              xaxisname[xaxisnameLen] = '_';
+              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid);
               cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
+              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
             }
         }
 
       if ( gridInqYvalsPtr(gridID) )
         {
+          char yaxisname[CDI_MAX_NAME];
+          gridInqYname(gridID, yaxisname);
+          checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
+
           cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid);
           cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(ystdname)) )
-            cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
-          if ( (len = strlen(ylongname)) )
-            cdf_put_att_text(fileID, ncyvarid, "long_name", len, ylongname);
-          if ( (len = strlen(yunits)) )
-            cdf_put_att_text(fileID, ncyvarid, "units", len, yunits);
+          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
 
           /* attribute for Panoply */
           cdf_put_att_text(fileID, ncyvarid, "_CoordinateAxisType", 3, "Lat");
 
           if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              strcat(yaxisname, "_");
-              strcat(yaxisname, BNDS_NAME);
-              dimIDs[0] = ydimID;
-              dimIDs[1] = xdimID;
-              dimIDs[2] = nvdimID;
+              size_t yaxisnameLen = strlen(yaxisname);
+              yaxisname[yaxisnameLen] = '_';
+              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid);
               cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
+              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
             }
         }
 
@@ -1663,19 +1564,15 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 static
 void cdfDefRgrid(stream_t *streamptr, int gridID)
 {
-  char axisname[7] = "rgridX";
-  int index, iz = 0;
   int dimID = UNDEFID;
-  int lwarn = TRUE;
 
   int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
   int ngrids = vlistNgrids(vlistID);
 
   size_t dimlen = (size_t)gridInqSize(gridID);
 
-  for ( index = 0; index < ngrids; index++ )
+  int iz = 0;
+  for ( int index = 0; index < ngrids; index++ )
     {
       if ( streamptr->xdimID[index] != UNDEFID )
         {
@@ -1690,21 +1587,23 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
                   dimID = streamptr->xdimID[index];
                   break;
                 }
-              else
-                iz++;
+              iz++;
             }
         }
     }
 
   if ( dimID == UNDEFID )
     {
+      int fileID  = streamptr->fileID;
+      static bool lwarn = true;
       if ( lwarn )
         {
           Warning("Creating a NetCDF file with data on a gaussian reduced grid.");
           Warning("The further processing of the resulting file is unsupported!");
-          lwarn = FALSE;
+          lwarn = false;
         }
 
+      char axisname[7] = "rgridX";
       if ( iz == 0 ) axisname[5] = '\0';
       else           sprintf(&axisname[5], "%1d", iz+1);
 
@@ -1723,18 +1622,16 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
 static
 void cdfDefGdim(stream_t *streamptr, int gridID)
 {
-  int index, iz = 0;
+  int iz = 0;
   int dimID = UNDEFID;
 
   int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
   int ngrids = vlistNgrids(vlistID);
 
   size_t dimlen = (size_t)gridInqSize(gridID);
 
   if ( gridInqYsize(gridID) == 0 )
-    for ( index = 0; index < ngrids; index++ )
+    for ( int index = 0; index < ngrids; index++ )
       {
         if ( streamptr->xdimID[index] != UNDEFID )
           {
@@ -1755,7 +1652,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
       }
 
   if ( gridInqXsize(gridID) == 0 )
-    for ( index = 0; index < ngrids; index++ )
+    for ( int index = 0; index < ngrids; index++ )
       {
         if ( streamptr->ydimID[index] != UNDEFID )
           {
@@ -1777,18 +1674,15 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
-      char axisname[CDI_MAX_NAME];
-      strcpy(axisname, "gsize");
+      int fileID  = streamptr->fileID;
+      char dimname[CDI_MAX_NAME];
+      strcpy(dimname, "gsize");
+
+      dimID = checkDimName(fileID, dimlen, dimname);
 
-      checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
-      /*
-      if ( iz == 0 ) axisname[5] = '\0';
-      else           sprintf(&axisname[5], "%1d", iz+1);
-      */
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      //printf("axisname, dimlen %s %d\n", axisname, dimlen);
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
 
       cdf_enddef(fileID);
       streamptr->ncmode = 2;
@@ -1809,14 +1703,9 @@ void cdfDefGridReference(stream_t *streamptr, int gridID)
       cdf_put_att_int(fileID, NC_GLOBAL, "number_of_grid_used", NC_INT, 1, &number);
     }
 
-  if ( gridInqReference(gridID, NULL) )
-    {
-      char gridfile[8912];
-      gridInqReference(gridID, gridfile);
-
-      if ( gridfile[0] != 0 )
-        cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile);
-    }
+  const char *gridfile = gridInqReferencePtr(gridID);
+  if ( gridfile && gridfile[0] != 0 )
+    cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile);
 }
 
 static
@@ -1862,17 +1751,7 @@ void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID)
 static
 void cdfDefUnstructured(stream_t *streamptr, int gridID)
 {
-  char xunits[CDI_MAX_NAME];
-  char xlongname[CDI_MAX_NAME];
-  char xstdname[CDI_MAX_NAME];
-  char yunits[CDI_MAX_NAME];
-  char ylongname[CDI_MAX_NAME];
-  char ystdname[CDI_MAX_NAME];
-  char xaxisname[CDI_MAX_NAME];
-  char yaxisname[CDI_MAX_NAME];
-  int index;
   int dimID = UNDEFID;
-  size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
   int nvdimID = UNDEFID;
@@ -1888,16 +1767,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
   size_t dimlen = (size_t)gridInqSize(gridID);
   int gridindex = vlistGridIndex(vlistID, gridID);
 
-  gridInqXname(gridID, xaxisname);
-  gridInqXlongname(gridID, xlongname);
-  gridInqXstdname(gridID, xstdname);
-  gridInqXunits(gridID, xunits);
-  gridInqYname(gridID, yaxisname);
-  gridInqYlongname(gridID, ylongname);
-  gridInqYstdname(gridID, ystdname);
-  gridInqYunits(gridID, yunits);
-
-  for ( index = 0; index < ngrids; index++ )
+  for ( int index = 0; index < ngrids; index++ )
     {
       if ( streamptr->xdimID[index] != UNDEFID )
         {
@@ -1909,7 +1779,9 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
               if ( dimlen == dimlen0 )
 		if ( gridInqNvertex(gridID0) == gridInqNvertex(gridID) &&
 		     IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
+		     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
 		  {
 		    dimID = streamptr->xdimID[index];
                     ncxvarid = streamptr->ncxvarID[index];
@@ -1923,22 +1795,26 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
-      char axisname[CDI_MAX_NAME];
-      char vertname[CDI_MAX_NAME];
-      strcpy(axisname, "ncells");
-      strcpy(vertname, "vertices");
-
-      checkGridName('V', xaxisname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('V', yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
-      checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
-      checkGridName('D', vertname, fileID, vlistID, gridID, ngrids, 'X');
-
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      {
+        char xdimname[CDI_MAX_NAME+3];
+        xdimname[0] = 0;
+        cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname);
+        if ( xdimname[0] == 0 ) strcpy(xdimname, "ncells");
+        dimID = checkDimName(fileID, dimlen, xdimname);
+        if ( dimID == UNDEFID ) cdf_def_dim(fileID, xdimname, dimlen, &dimID);
+      }
 
       size_t nvertex = (size_t)gridInqNvertex(gridID);
-      if ( nvertex > 0 ) cdf_def_dim(fileID, vertname, nvertex, &nvdimID);
+      if ( nvertex > 0 )
+        {
+          char vdimname[CDI_MAX_NAME+3];
+          vdimname[0] = 0;
+          cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname);
+          if ( vdimname[0] == 0 ) strcpy(vdimname, "vertices");
+          nvdimID = checkDimName(fileID, nvertex, vdimname);
+          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
+        }
 
       cdfDefGridReference(streamptr, gridID);
 
@@ -1946,53 +1822,47 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
       if ( gridInqXvalsPtr(gridID) )
         {
+          char xaxisname[CDI_MAX_NAME];
+          gridInqXname(gridID, xaxisname);
+          checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X');
           cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid);
           cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(xstdname)) )
-            cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
-          if ( (len = strlen(xlongname)) )
-            cdf_put_att_text(fileID, ncxvarid, "long_name", len, xlongname);
-          if ( (len = strlen(xunits)) )
-            cdf_put_att_text(fileID, ncxvarid, "units", len, xunits);
+          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
 
           if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              int dimIDs[2];
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              strcat(xaxisname, "_");
-              strcat(xaxisname, BNDS_NAME);
+              int dimIDs[2] = { dimID, nvdimID };
+              size_t xaxisnameLen = strlen(xaxisname);
+              xaxisname[xaxisnameLen] = '_';
+              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid);
               cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
+              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
             }
         }
 
       if ( gridInqYvalsPtr(gridID) )
         {
+          char yaxisname[CDI_MAX_NAME];
+          gridInqYname(gridID, yaxisname);
+          checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
           cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid);
           cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-          if ( (len = strlen(ystdname)) )
-            cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
-          if ( (len = strlen(ylongname)) )
-            cdf_put_att_text(fileID, ncyvarid, "long_name", len, ylongname);
-          if ( (len = strlen(yunits)) )
-            cdf_put_att_text(fileID, ncyvarid, "units", len, yunits);
+          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
 
           if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
             {
-              int dimIDs[2];
-              dimIDs[0] = dimID;
-              dimIDs[1] = nvdimID;
-              strcat(yaxisname, "_");
-              strcat(yaxisname, BNDS_NAME);
+              int dimIDs[2] = { dimID, nvdimID };
+              size_t yaxisnameLen = strlen(yaxisname);
+              yaxisname[yaxisnameLen] = '_';
+              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
               cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid);
               cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
-              cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
+              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
             }
         }
 
@@ -2026,6 +1896,12 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
   streamptr->ncavarID[gridindex] = ncavarid;
 }
 
+struct attTxtTab2
+{
+  const char *attName, *attVal;
+  size_t valLen;
+};
+
 static
 void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
 {
@@ -2042,7 +1918,6 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
       int ncdimid, ncdimid2;
       int hyaiid, hybiid, hyamid, hybmid;
       double mval;
-      char tmpname[CDI_MAX_NAME];
 
       if ( streamptr->vct.ilev > 0 )
         {
@@ -2068,22 +1943,34 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
       cdf_def_var(fileID, "hyam", NC_DOUBLE, 1, &ncdimid,  &hyamid);
       cdf_def_var(fileID, "hybm", NC_DOUBLE, 1, &ncdimid,  &hybmid);
 
-      strcpy(tmpname, "hybrid A coefficient at layer interfaces");
-      cdf_put_att_text(fileID, hyaiid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "Pa");
-      cdf_put_att_text(fileID, hyaiid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hybrid B coefficient at layer interfaces");
-      cdf_put_att_text(fileID, hybiid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "1");
-      cdf_put_att_text(fileID, hybiid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hybrid A coefficient at layer midpoints");
-      cdf_put_att_text(fileID, hyamid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "Pa");
-      cdf_put_att_text(fileID, hyamid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hybrid B coefficient at layer midpoints");
-      cdf_put_att_text(fileID, hybmid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "1");
-      cdf_put_att_text(fileID, hybmid, "units", strlen(tmpname), tmpname);
+      {
+        static const char lname_n[] = "long_name",
+          lname_v_ai[] = "hybrid A coefficient at layer interfaces",
+          units_n[] = "units",
+          units_v_ai[] = "Pa",
+          lname_v_bi[] = "hybrid B coefficient at layer interfaces",
+          units_v_bi[] = "1",
+          lname_v_am[] = "hybrid A coefficient at layer midpoints",
+          units_v_am[] = "Pa",
+          lname_v_bm[] = "hybrid B coefficient at layer midpoints",
+          units_v_bm[] = "1";
+        static const struct attTxtTab2 tab[]
+          = {
+          { lname_n, lname_v_ai, sizeof (lname_v_ai) - 1 },
+          { units_n, units_v_ai, sizeof (units_v_ai) - 1 },
+          { lname_n, lname_v_bi, sizeof (lname_v_bi) - 1 },
+          { units_n, units_v_bi, sizeof (units_v_bi) - 1 },
+          { lname_n, lname_v_am, sizeof (lname_v_am) - 1 },
+          { units_n, units_v_am, sizeof (units_v_am) - 1 },
+          { lname_n, lname_v_bm, sizeof (lname_v_bm) - 1 },
+          { units_n, units_v_bm, sizeof (units_v_bm) - 1 },
+        };
+        enum { tabLen = sizeof (tab) / sizeof (tab[0]) };
+        int ids[tabLen] = { hyaiid, hyaiid, hybiid, hybiid,
+                            hyamid, hyamid, hybmid, hybmid };
+        for ( size_t i = 0; i < tabLen; ++i )
+          cdf_put_att_text(fileID, ids[i], tab[i].attName, tab[i].valLen, tab[i].attVal);
+      }
 
       cdf_enddef(fileID);
       streamptr->ncmode = 2;
@@ -2116,7 +2003,6 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
 
       int mlev = ilev - 1;
       int hyaiid = 0, hybiid = 0, hyamid, hybmid;
-      char tmpname[CDI_MAX_NAME];
 
       if ( streamptr->vct.ilev > 0 )
         {
@@ -2141,28 +2027,43 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
       cdf_def_var(fileID, "ap", NC_DOUBLE, 1, dimIDs,  &hyamid);
       cdf_def_var(fileID, "b",  NC_DOUBLE, 1, dimIDs,  &hybmid);
 
-      strcpy(tmpname, "vertical coordinate formula term: ap(k)");
-      cdf_put_att_text(fileID, hyamid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "Pa");
-      cdf_put_att_text(fileID, hyamid, "units", strlen(tmpname), tmpname);
-      strcpy(tmpname, "vertical coordinate formula term: b(k)");
-      cdf_put_att_text(fileID, hybmid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "1");
-      cdf_put_att_text(fileID, hybmid, "units", strlen(tmpname), tmpname);
+      {
+        static const char lname[] = "vertical coordinate formula term: ap(k)";
+        cdf_put_att_text(fileID, hyamid, "long_name", sizeof (lname) - 1, lname);
+      }
+      {
+        static const char units[] = "Pa";
+        cdf_put_att_text(fileID, hyamid, "units", sizeof (units) - 1, units);
+      }
+      {
+        static const char lname[] = "vertical coordinate formula term: b(k)";
+        cdf_put_att_text(fileID, hybmid, "long_name", sizeof (lname) - 1, lname);
+      }
+      {
+        static const char units[] = "1";
+        cdf_put_att_text(fileID, hybmid, "units", sizeof (units) - 1, units);
+      }
 
       if ( ncbndsID != -1 )
         {
           cdf_def_var(fileID, "ap_bnds", NC_DOUBLE, 2, dimIDs, &hyaiid);
           cdf_def_var(fileID, "b_bnds",  NC_DOUBLE, 2, dimIDs, &hybiid);
-
-          strcpy(tmpname, "vertical coordinate formula term: ap(k+1/2)");
-          cdf_put_att_text(fileID, hyaiid, "long_name", strlen(tmpname), tmpname);
-          strcpy(tmpname, "Pa");
-          cdf_put_att_text(fileID, hyaiid, "units", strlen(tmpname), tmpname);
-          strcpy(tmpname, "vertical coordinate formula term: b(k+1/2)");
-          cdf_put_att_text(fileID, hybiid, "long_name", strlen(tmpname), tmpname);
-          strcpy(tmpname, "1");
-          cdf_put_att_text(fileID, hybiid, "units", strlen(tmpname), tmpname);
+          {
+            static const char lname[] = "vertical coordinate formula term: ap(k+1/2)";
+            cdf_put_att_text(fileID, hyaiid, "long_name", sizeof (lname) - 1, lname);
+          }
+          {
+            static const char units[] = "Pa";
+            cdf_put_att_text(fileID, hyaiid, "units", sizeof (units) - 1, units);
+          }
+          {
+            static const char lname[] = "vertical coordinate formula term: b(k+1/2)";
+            cdf_put_att_text(fileID, hybiid, "long_name", sizeof (lname) - 1, lname);
+          }
+          {
+            static const char units[] = "1";
+            cdf_put_att_text(fileID, hybiid, "units", sizeof (units) - 1, units);
+          }
         }
 
       cdf_enddef(fileID);
@@ -2198,10 +2099,11 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
     }
 }
 
+struct attTxtTab { const char *txt; size_t txtLen; };
+
 static
 void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
 {
-  char tmpname[CDI_MAX_NAME];
   int fileID  = streamptr->fileID;
 
   if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
@@ -2209,32 +2111,50 @@ void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int
   cdf_def_dim(fileID, axisname, dimlen, dimID);
   cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
 
-  strcpy(tmpname, "hybrid_sigma_pressure");
-  cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(tmpname), tmpname);
+  {
+    static const char sname[] = "hybrid_sigma_pressure";
+    cdf_put_att_text(fileID, ncvarid, "standard_name", sizeof (sname) - 1, sname);
+  }
+  {
+    static const char *attName[] = {
+      "long_name",
+      "formula",
+      "formula_terms"
+    };
+    enum { nAtt = sizeof (attName) / sizeof (attName[0]) };
+    static const char lname_m[] = "hybrid level at layer midpoints",
+      formula_m[] = "hyam hybm (mlev=hyam+hybm*aps)",
+      fterms_m[] = "ap: hyam b: hybm ps: aps",
+      lname_i[] = "hybrid level at layer interfaces",
+      formula_i[] = "hyai hybi (ilev=hyai+hybi*aps)",
+      fterms_i[] = "ap: hyai b: hybi ps: aps";
+    static const struct attTxtTab tab[2][nAtt] = {
+      {
+        { lname_i, sizeof (lname_i) - 1 },
+        { formula_i, sizeof (formula_i) - 1 },
+        { fterms_i, sizeof (fterms_i) - 1 }
+      },
+      {
+        { lname_m, sizeof (lname_m) - 1 },
+        { formula_m, sizeof (formula_m) - 1 },
+        { fterms_m, sizeof (fterms_m) - 1 }
+      }
+    };
 
-  if ( type == ZAXIS_HYBRID )
-    {
-      strcpy(tmpname, "hybrid level at layer midpoints");
-      cdf_put_att_text(fileID, ncvarid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hyam hybm (mlev=hyam+hybm*aps)");
-      cdf_put_att_text(fileID, ncvarid, "formula", strlen(tmpname), tmpname);
-      strcpy(tmpname, "ap: hyam b: hybm ps: aps");
-      cdf_put_att_text(fileID, ncvarid, "formula_terms", strlen(tmpname), tmpname);
-    }
-  else
-    {
-      strcpy(tmpname, "hybrid level at layer interfaces");
-      cdf_put_att_text(fileID, ncvarid, "long_name", strlen(tmpname), tmpname);
-      strcpy(tmpname, "hyai hybi (ilev=hyai+hybi*aps)");
-      cdf_put_att_text(fileID, ncvarid, "formula", strlen(tmpname), tmpname);
-      strcpy(tmpname, "ap: hyai b: hybi ps: aps");
-      cdf_put_att_text(fileID, ncvarid, "formula_terms", strlen(tmpname), tmpname);
-    }
+    size_t tabSelect = type == ZAXIS_HYBRID;
+    for (size_t i = 0; i < nAtt; ++i)
+      cdf_put_att_text(fileID, ncvarid, attName[i],
+                       tab[tabSelect][i].txtLen, tab[tabSelect][i].txt);
+  }
 
-  strcpy(tmpname, "level");
-  cdf_put_att_text(fileID, ncvarid, "units", strlen(tmpname), tmpname);
-  strcpy(tmpname, "down");
-  cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
+  {
+    static const char units[] = "level";
+    cdf_put_att_text(fileID, ncvarid, "units", sizeof (units) - 1, units);
+  }
+  {
+    static const char direction[] = "down";
+    cdf_put_att_text(fileID, ncvarid, "positive", sizeof (direction) - 1, direction);
+  }
 
   cdf_enddef(fileID);
   streamptr->ncmode = 2;
@@ -2268,24 +2188,34 @@ void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zax
   cdf_def_dim(fileID, axisname, dimlen, dimID);
   cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
 
-  char tmpname[CDI_MAX_NAME];
-  strcpy(tmpname, "atmosphere_hybrid_sigma_pressure_coordinate");
-  cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(tmpname), tmpname);
-
-  strcpy(tmpname, "hybrid sigma pressure coordinate");
-  cdf_put_att_text(fileID, ncvarid, "long_name", strlen(tmpname), tmpname);
-  strcpy(tmpname, "p = ap + b*ps");
-  cdf_put_att_text(fileID, ncvarid, "formula", strlen(tmpname), tmpname);
-  strcpy(tmpname, "ap: ap b: b ps: ");
-  strcat(tmpname, psname);
-  cdf_put_att_text(fileID, ncvarid, "formula_terms", strlen(tmpname), tmpname);
-
-  strcpy(tmpname, "1");
-  cdf_put_att_text(fileID, ncvarid, "units", strlen(tmpname), tmpname);
-  strcpy(tmpname, "Z");
-  cdf_put_att_text(fileID, ncvarid, "axis", strlen(tmpname), tmpname);
-  strcpy(tmpname, "down");
-  cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
+  {
+    static const char sname[] = "standard_name",
+      sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
+      lname[] = "long_name",
+      lname_v[] = "hybrid sigma pressure coordinate",
+      formula[] = "formula",
+      formula_v[] = "p = ap + b*ps",
+      fterms[] = "formula_terms",
+      fterms_v[] = "ap: ap b: b ps: ",
+      units[] = "units",
+      units_v[] = "1",
+      axis[] = "axis",
+      axis_v[] = "Z",
+      direction[] = "positive",
+      direction_v[] = "down";
+    struct attTxtTab2 tab[] = {
+      { sname, sname_v, sizeof (sname_v) - 1 },
+      { lname, lname_v, sizeof (lname_v) - 1 },
+      { formula, formula_v, sizeof (formula_v) - 1 },
+      { fterms, fterms_v, sizeof (fterms_v) - 1 },
+      { units, units_v, sizeof (units_v) - 1 },
+      { axis, axis_v, sizeof (axis_v) - 1 },
+      { direction, direction_v, sizeof (direction_v) - 1 },
+    };
+    enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
+    for (size_t i = 0; i < nAtt; ++i)
+      cdf_put_att_text(fileID, ncvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
+  }
 
   int ncbvarid = UNDEFID;
   int nvdimID = UNDEFID;
@@ -2308,31 +2238,41 @@ void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zax
 
   //if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
     {
-      int dimIDs[2];
       size_t nvertex = 2;
-      if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-        cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+        cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
 
       if ( nvdimID != UNDEFID )
         {
-          strcat(axisname, "_");
-          strcat(axisname, BNDS_NAME);
-          dimIDs[0] = *dimID;
-          dimIDs[1] = nvdimID;
+          size_t axisnameLen = strlen(axisname);
+          axisname[axisnameLen] = '_';
+          memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
+          axisnameLen += sizeof (bndsName);
+          int dimIDs[2] = { *dimID, nvdimID };
           cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
-          cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
-
-          strcpy(tmpname, "atmosphere_hybrid_sigma_pressure_coordinate");
-          cdf_put_att_text(fileID, ncbvarid, "standard_name", strlen(tmpname), tmpname);
-
-          strcpy(tmpname, "p = ap + b*ps");
-          cdf_put_att_text(fileID, ncbvarid, "formula", strlen(tmpname), tmpname);
-          strcpy(tmpname, "ap: ap_bnds b: b_bnds ps: ");
-          strcat(tmpname, psname);
-          cdf_put_att_text(fileID, ncbvarid, "formula_terms", strlen(tmpname), tmpname);
-
-          strcpy(tmpname, "1");
-          cdf_put_att_text(fileID, ncbvarid, "units", strlen(tmpname), tmpname);
+          cdf_put_att_text(fileID, ncvarid, "bounds", axisnameLen, axisname);
+          {
+            static const char sname[] = "standard_name",
+              sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
+              formula[] = "formula",
+              formula_v[] = "p = ap + b*ps";
+            struct attTxtTab2 tab[] = {
+              { sname, sname_v, sizeof (sname_v) - 1 },
+              { formula, formula_v, sizeof (formula_v) - 1 },
+            };
+            enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
+            for (size_t i = 0; i < nAtt; ++i)
+              cdf_put_att_text(fileID, ncbvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
+          }
+          {
+            char txt[CDI_MAX_NAME];
+            size_t len = (size_t)(sprintf(txt, "%s%s", "ap: ap_bnds b: b_bnds ps: ", psname));
+            cdf_put_att_text(fileID, ncbvarid, "formula_terms", len, txt);
+          }
+          {
+            static const char units[] = "1";
+            cdf_put_att_text(fileID, ncbvarid, "units", sizeof (units) - 1, units);
+          }
         }
     }
 
@@ -2377,20 +2317,11 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 {
   /*  char zaxisname0[CDI_MAX_NAME]; */
   char axisname[CDI_MAX_NAME];
-  char stdname[CDI_MAX_NAME];
-  char longname[CDI_MAX_NAME];
-  char units[CDI_MAX_NAME];
-  char tmpname[CDI_MAX_NAME];
-  int index;
-  int zaxisID0;
   int dimID = UNDEFID;
   int dimIDs[2];
-  size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
   int nvdimID = UNDEFID;
-  int ilevel = 0;
   int xtype = NC_DOUBLE;
-  int positive;
 
   if ( zaxisInqPrec(zaxisID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
 
@@ -2438,65 +2369,17 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
       }
 
   zaxisInqName(zaxisID, axisname);
-  /*
-  for ( index = 0; index < nzaxis; index++ )
-    {
-      if ( streamptr->zaxisID[index] != UNDEFID )
-        {
-          zaxisID0 = vlistZaxis(vlistID, index);
-          zaxisInqName(zaxisID0, zaxisname0);
-          if ( strcmp(zaxisname0, axisname) == 0 ) ilevel++;
-        }
-    }
-  */
+
   if ( dimID == UNDEFID )
     {
-      char axisname0[CDI_MAX_NAME];
-      char axisname2[CDI_MAX_NAME];
-      int checkname = FALSE;
-      int status;
-
-      /* check that the name is not already defined */
-      checkname = TRUE;
-      ilevel = 0;
-
-      while ( checkname )
-        {
-          strcpy(axisname2, axisname);
-          if ( ilevel ) sprintf(&axisname2[strlen(axisname2)], "_%d", ilevel+1);
-
-          status = nc_inq_varid(fileID, axisname2, &ncvarid);
-          if ( status != NC_NOERR )
-            {
-              if ( ilevel )
-                {
-                  /* check that the name does not exist for other zaxes */
-                  for ( index = 0; index < nzaxis; index++ )
-                    {
-                      zaxisID0 = vlistZaxis(vlistID, index);
-                      if ( zaxisID != zaxisID0 )
-                        {
-                          zaxisInqName(zaxisID0, axisname0);
-                          if ( strcmp(axisname0, axisname2) == 0 ) break;
-                        }
-                    }
-                  if ( index == nzaxis ) checkname = FALSE;
-                }
-              else
-                {
-                  checkname = FALSE;
-                }
-            }
-
-          if ( checkname ) ilevel++;
-
-          if ( ilevel > 99 ) break;
-        }
+      checkZaxisName(axisname, fileID, vlistID, zaxisID, nzaxis);
 
-      if ( ilevel ) sprintf(&axisname[strlen(axisname)], "_%1d", ilevel+1);
+      char dimname[CDI_MAX_NAME+3];
+      dimname[0] = 0;
+      //cdiZaxisInqString(zaxisID, CDI_ZAXIS_DIMNAME, CDI_MAX_NAME, dimname);
+      if ( dimname[0] == 0 ) strcpy(dimname, axisname);
 
-      if ( type == ZAXIS_REFERENCE )
-	cdfDefZaxisUUID(streamptr, zaxisID);
+      if ( type == ZAXIS_REFERENCE ) cdfDefZaxisUUID(streamptr, zaxisID);
 
       if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
         {
@@ -2504,48 +2387,45 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
         }
       else
         {
-          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+          dimID = checkDimName(fileID, dimlen, dimname);
 
-          if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
+          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-          zaxisInqLongname(zaxisID, longname);
-          zaxisInqUnits(zaxisID, units);
-          zaxisInqStdname(zaxisID, stdname);
+          if ( ndims && dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
 
           cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
 
-          if ( (len = strlen(stdname)) )
-            cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-          if ( (len = strlen(longname)) )
-            cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-          if ( (len = strlen(units)) )
-            cdf_put_att_text(fileID, ncvarid, "units", len, units);
-
-	  positive = zaxisInqPositive(zaxisID);
-	  if ( positive == POSITIVE_UP )
-	    {
-	      strcpy(tmpname, "up");
-	      cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
-	    }
-	  else if ( positive == POSITIVE_DOWN )
-	    {
-	      strcpy(tmpname, "down");
-	      cdf_put_att_text(fileID, ncvarid, "positive", strlen(tmpname), tmpname);
-	    }
+          cdfPutGridStdAtts(fileID, ncvarid, zaxisID, &gridInqsZ);
 
+          {
+            int positive = zaxisInqPositive(zaxisID);
+            static const char positive_up[] = "up",
+              positive_down[] = "down";
+            static const struct attTxtTab tab[2] = {
+              { positive_up, sizeof (positive_up) - 1 },
+              { positive_down, sizeof (positive_down) - 1 },
+            };
+            if ( positive == POSITIVE_UP || positive == POSITIVE_DOWN )
+              {
+                size_t select = positive == POSITIVE_DOWN;
+                cdf_put_att_text(fileID, ncvarid, "positive",
+                                 tab[select].txtLen, tab[select].txt);
+              }
+          }
           cdf_put_att_text(fileID, ncvarid, "axis", 1, "Z");
 
 	  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
             {
               size_t nvertex = 2;
-	      if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
-		cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+	      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+		cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
 
 	      if ( nvdimID != UNDEFID )
 		{
-		  strcat(axisname, "_");
-		  strcat(axisname, BNDS_NAME);
-		  if ( ndims ) dimIDs[0] = dimID;
+                  size_t axisnameLen = strlen(axisname);
+                  axisname[axisnameLen] = '_';
+                  memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
+		  dimIDs[0] = dimID;
 		  dimIDs[ndims] = nvdimID;
 		  cdf_def_var(fileID, axisname, (nc_type) xtype, ndims+1, dimIDs, &ncbvarid);
 		  cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
@@ -2583,8 +2463,8 @@ static
 void cdfDefPole(stream_t *streamptr, int gridID)
 {
   int ncvarid = UNDEFID;
-  char varname[] = "rotated_pole";
-  char mapname[] = "rotated_latitude_longitude";
+  static const char varname[] = "rotated_pole";
+  static const char mapname[] = "rotated_latitude_longitude";
 
   int fileID  = streamptr->fileID;
 
@@ -2597,7 +2477,7 @@ void cdfDefPole(stream_t *streamptr, int gridID)
   int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
   if ( ncerrcode == NC_NOERR )
     {
-      cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
+      cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", sizeof (mapname) - 1, mapname);
       cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole);
       cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole);
       if ( IS_NOT_EQUAL(angle, 0) )
@@ -2995,6 +2875,7 @@ void init_ncvars(long nvars, ncvar_t *ncvars)
       ncvars[ncvarid].zvarid          = UNDEFID;
       ncvars[ncvarid].tvarid          = UNDEFID;
       ncvars[ncvarid].psvarid         = UNDEFID;
+      ncvars[ncvarid].p0varid         = UNDEFID;
       ncvars[ncvarid].ncoordvars      = 0;
       for ( int i = 0; i < MAX_COORDVARS; ++i )
         ncvars[ncvarid].coordvarids[i]  = UNDEFID;
@@ -3163,9 +3044,9 @@ bool isDepthAxis(const char *stdname, const char *longname)
 {
   bool status = false;
 
-  if ( strcmp(stdname, "depth") == 0 ) status = true;
-
-  if ( status == false )
+  if ( strcmp(stdname, "depth") == 0 )
+    status = true;
+  else
     if ( strcmp(longname, "depth_below_sea") == 0 ||
          strcmp(longname, "depth below sea") == 0 )
       {
@@ -3180,9 +3061,9 @@ bool isHeightAxis(const char *stdname, const char *longname)
 {
   bool status = false;
 
-  if ( strcmp(stdname, "height") == 0 ) status = true;
-
-  if ( status == false )
+  if ( strcmp(stdname, "height") == 0 )
+    status = true;
+  else
     if ( strcmp(longname, "height") == 0 ||
          strcmp(longname, "height above the surface") == 0 )
       {
@@ -3197,11 +3078,11 @@ bool unitsIsPressure(const char *units)
 {
   bool status = false;
 
-  if ( memcmp(units, "millibar", 8) == 0 ||
-       memcmp(units, "mb", 2)       == 0 ||
-       memcmp(units, "hectopas", 8) == 0 ||
-       memcmp(units, "hPa", 3)      == 0 ||
-       memcmp(units, "Pa", 2)       == 0 )
+  if ( strncmp(units, "millibar", 8) == 0 ||
+       strncmp(units, "mb", 2)       == 0 ||
+       strncmp(units, "hectopas", 8) == 0 ||
+       strncmp(units, "hPa", 3)      == 0 ||
+       strncmp(units, "Pa", 2)       == 0 )
     {
       status = true;
     }
@@ -3210,15 +3091,19 @@ bool unitsIsPressure(const char *units)
 }
 
 static
-void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid)
+int scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid, int *avarid, int *p0varid)
 {
+  int status = 0;
   *apvarid = -1;
   *bvarid  = -1;
   *psvarid = -1;
-  const int attstringlen = 8192; char attstring[8192];
+  *avarid  = -1;
+  *p0varid = -1;
+  enum { attstringlen = 8192 }; char attstring[attstringlen];
   cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring);
   if ( strcmp(attstring, "p = ap + b*ps") == 0 )
     {
+      status = 1;
       int lstop = FALSE;
       int dimvarid;
       cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
@@ -3240,8 +3125,8 @@ void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int
           if ( *pstring == 0 ) lstop = TRUE;
           *pstring++ = 0;
 
-          int status = nc_inq_varid(ncid, varname, &dimvarid);
-          if ( status == NC_NOERR )
+          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
+          if ( status_nc == NC_NOERR )
             {
               if      ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid;
               else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
@@ -3249,12 +3134,54 @@ void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int
             }
           else if ( strcmp(tagname, "ps:") != 0 )
             {
-              Warning("%s - %s", nc_strerror(status), varname);
+              Warning("%s - %s", nc_strerror(status_nc), varname);
+            }
+
+          if ( lstop ) break;
+        }
+    }
+  else if ( strcmp(attstring, "xxxp = a*p0 + b*ps") == 0 )
+    {
+      status = 2;
+      int lstop = FALSE;
+      int dimvarid;
+      cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
+      char *pstring = attstring;
+
+      for ( int i = 0; i < 4; i++ )
+        {
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *tagname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = TRUE;
+          *pstring++ = 0;
+
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *varname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = TRUE;
+          *pstring++ = 0;
+
+          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
+          if ( status_nc == NC_NOERR )
+            {
+              if      ( strcmp(tagname, "a:")  == 0 ) *avarid  = dimvarid;
+              else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
+              else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
+              else if ( strcmp(tagname, "p0:") == 0 ) *p0varid = dimvarid;
+            }
+          else if ( strcmp(tagname, "ps:") != 0 )
+            {
+              Warning("%s - %s", nc_strerror(status_nc), varname);
             }
 
           if ( lstop ) break;
         }
     }
+
+  return status;
 }
 
 static
@@ -3273,28 +3200,37 @@ bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, con
       int dimid = ncvar->dimids[0];
       size_t dimlen = ncdims[dimid].len;
 
-      int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1;
+      int ret;
+      int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1, avarid1 = -1, p0varid1 = -1;
       if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
-        scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1);
+        ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1, &avarid1, &p0varid1);
       if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE;
       if ( bvarid1  != -1 ) ncvars[bvarid1].isvar  = FALSE;
       if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1;
+      if ( avarid1  != -1 ) ncvars[avarid1].isvar = FALSE;
+      if ( p0varid1 != -1 ) ncvar->p0varid = p0varid1;
 
       if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms )
         {
           ncfvarid = ncvar->bounds;
-          int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1;
+          int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1, avarid2 = -1, p0varid2 = -1;
+          ret = 0;
           if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
-            scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2);
-          if ( apvarid2 != -1 && bvarid2 != -1 )
+            ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2, &avarid2, &p0varid2);
+          if ( ret == 1 ) avarid2 = apvarid2;
+          if ( avarid2 != -1 && bvarid2 != -1 )
             {
-              ncvars[apvarid2].isvar = FALSE;
+              ncvars[avarid2].isvar = FALSE;
               ncvars[bvarid2].isvar  = FALSE;
 
-              if ( dimid == ncvars[apvarid2].dimids[0] && ncdims[ncvars[apvarid2].dimids[1]].len == 2 )
+              if ( dimid == ncvars[avarid2].dimids[0] && ncdims[ncvars[avarid2].dimids[1]].len == 2 )
                 {
+                  double px = 1;
+                  if ( ret == 2 && p0varid1 == p0varid2 )
+                    cdf_get_var_double(ncid, p0varid2, &px);
+
                   double abuf[dimlen*2], bbuf[dimlen*2];
-                  cdf_get_var_double(ncid, apvarid2, abuf);
+                  cdf_get_var_double(ncid, avarid2, abuf);
                   cdf_get_var_double(ncid, bvarid2, bbuf);
                   /*
                   for ( int i = 0; i < dimlen; ++i )
@@ -3310,6 +3246,9 @@ bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, con
                   vct[dimlen]     = abuf[dimlen*2-1];
                   vct[dimlen*2+1] = bbuf[dimlen*2-1];
 
+                  if ( ret == 2 && IS_NOT_EQUAL(px, 1) )
+                    for ( size_t i = 0; i < dimlen+1; ++i ) vct[i] *= px;
+
                   ncvar->vct = vct;
                   ncvar->vctsize = vctsize;
                 }
@@ -3445,7 +3384,6 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 #if  defined  (HAVE_NETCDF4)
       if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 )
         {
-          char buf[CDI_MAX_NAME];
           int shuffle, deflate, deflate_level;
           size_t chunks[nvdims];
           int storage_in;
@@ -3464,14 +3402,19 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                       for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]);
                       fprintf(stderr, "\n");
                     }
-                  strcat(ncvars[ncvarid].extra, "chunks=");
-                  for ( int i = nvdims-1; i >= 0; --i )
-                    {
-                      sprintf(buf, "%ld", (long) chunks[i]);
-                      strcat(ncvars[ncvarid].extra, buf);
-                      if ( i > 0 ) strcat(ncvars[ncvarid].extra, "x");
-                    }
-                  strcat(ncvars[ncvarid].extra, " ");
+                  {
+                    char *buf = ncvars[ncvarid].extra;
+                    size_t pos = strlen(buf);
+                    static const char prefix[] = "chunks=";
+                    memcpy(buf + pos, prefix, sizeof (prefix));
+                    pos += sizeof (prefix) - 1;
+                    for ( int i = nvdims-1; i >= 0; --i )
+                      {
+                        pos += (size_t)(sprintf(buf + pos, "%zu%s", chunks[i],
+                                                i > 0 ? "x" : ""));
+                      }
+                    buf[pos] = ' '; buf[pos + 1] = 0;
+                  }
                 }
             }
         }
@@ -3705,17 +3648,15 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
             }
           else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
             {
-              char *cell_measures = NULL, *cell_var = NULL;
-
               cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
               char *pstring = attstring;
 
               while ( isspace((int) *pstring) ) pstring++;
-              cell_measures = pstring;
+              char *cell_measures = pstring;
               while ( isalnum((int) *pstring) ) pstring++;
               *pstring++ = 0;
               while ( isspace((int) *pstring) ) pstring++;
-              cell_var = pstring;
+              char *cell_var = pstring;
               while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++;
               *pstring++ = 0;
               /*
@@ -3768,8 +3709,6 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
           */
           else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
             {
-              int status;
-              char *varname = NULL;
               int lstop = FALSE;
               int dimvarid;
 
@@ -3780,12 +3719,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 {
                   while ( isspace((int) *pstring) ) pstring++;
                   if ( *pstring == 0 ) break;
-                  varname = pstring;
+                  char *varname = pstring;
                   while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
                   if ( *pstring == 0 ) lstop = TRUE;
                   *pstring++ = 0;
 
-                  status = nc_inq_varid(ncid, varname, &dimvarid);
+                  int status = nc_inq_varid(ncid, varname, &dimvarid);
                   if ( status == NC_NOERR )
                     {
                       cdfSetVar(ncvars, dimvarid, FALSE);
@@ -3815,8 +3754,6 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
             }
           else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
             {
-              int status;
-              char *varname = NULL;
               int lstop = FALSE;
               int dimvarid;
 
@@ -3827,12 +3764,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 {
                   while ( isspace((int) *pstring) ) pstring++;
                   if ( *pstring == 0 ) break;
-                  varname = pstring;
+                  char *varname = pstring;
                   while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
                   if ( *pstring == 0 ) lstop = TRUE;
                   *pstring++ = 0;
 
-                  status = nc_inq_varid(ncid, varname, &dimvarid);
+                  int status = nc_inq_varid(ncid, varname, &dimvarid);
                   if ( status == NC_NOERR )
                     {
                       cdfSetVar(ncvars, dimvarid, FALSE);
@@ -3897,8 +3834,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( ncvars[ncvarid].lvalidrange == FALSE )
                 {
                   extern int cdiIgnoreValidRange;
-                  int lignore = FALSE;
-                  if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
                   if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
                     {
                       cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange);
@@ -3918,8 +3854,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( ncvars[ncvarid].lvalidrange == FALSE )
                 {
                   extern int cdiIgnoreValidRange;
-                  int lignore = FALSE;
-                  if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
                   if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
                     {
                       cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]);
@@ -3936,8 +3871,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( ncvars[ncvarid].lvalidrange == FALSE )
                 {
                   extern int cdiIgnoreValidRange;
-                  int lignore = FALSE;
-                  if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
                   if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
                     {
                       cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]);
@@ -4653,7 +4587,7 @@ cdfLazyGridInqYVal(grid_t *grid, int index)
   return rv;
 }
 
-static int
+static bool
 cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef,
                        struct cdfLazyGrid *lazyGridTest)
 {
@@ -4673,10 +4607,10 @@ cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef,
     ||   valsGetYRef->varNCId     != valsGetYTest->varNCId;
 }
 
-static int
+static bool
 cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest)
 {
-  int diff;
+  bool diff;
   struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
   if (gridTest->vtable == &cdfLazyGridVtable)
     diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
@@ -4685,10 +4619,10 @@ cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest)
   return diff;
 }
 
-static int
+static bool
 cdfLazyCompareXYAO(grid_t *gridRef, grid_t *gridTest)
 {
-  int diff;
+  bool diff;
   struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
   if (gridTest->vtable == &cdfLazyGridVtable)
     diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
@@ -4972,6 +4906,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	{
           int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
 	  int xdimid = -1, ydimid = -1;
+          int vdimid = -1;
 	  int islon = 0, islat = 0;
 	  int nxdims = 0, nydims = 0;
           size_t size = 0;
@@ -5347,7 +5282,8 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 			int nbdims = ncvars[ncvars[xvarid].bounds].ndims;
 			if ( nbdims == 2 || nbdims == 3 )
 			  {
-			    size_t nvertex = ncdims[ncvars[ncvars[xvarid].bounds].dimids[nbdims-1]].len;
+                            vdimid = ncvars[ncvars[xvarid].bounds].dimids[nbdims-1];
+			    size_t nvertex = ncdims[vdimid].len;
 			    grid->nvertex = (int)nvertex;
                             if (CDI_netcdf_lazy_grid_load)
                               {
@@ -5392,9 +5328,8 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
                               }
                             else
                               {
-                                int vid
-                                  = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1];
-                                size_t nvertex = ncdims[vid].len;
+                                vdimid = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1];
+                                size_t nvertex = ncdims[vdimid].len;
                                 /*
                                   if ( nvertex != grid->nvertex )
                                   Warning("nvertex problem! nvertex x %d, nvertex y %d",
@@ -5450,7 +5385,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	      }
 	    }
 
-          if (grid->type != ncvars[ncvarid].gridtype)
+          if ( grid->type != ncvars[ncvarid].gridtype )
             {
               int gridtype = ncvars[ncvarid].gridtype;
               grid->type = gridtype;
@@ -5669,6 +5604,13 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
           if ( xdimid == -1 && ydimid == -1 && grid->size == 1 )
             gridDefHasDims(ncvars[ncvarid].gridID, FALSE);
 
+          if ( xdimid != -1 )
+            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_XDIMNAME, (int)(strlen(ncdims[xdimid].name)+1), ncdims[xdimid].name);
+          if ( ydimid != -1 )
+            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_YDIMNAME, (int)(strlen(ncdims[ydimid].name)+1), ncdims[ydimid].name);
+          if ( vdimid != -1 )
+            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_VDIMNAME, (int)(strlen(ncdims[vdimid].name)+1), ncdims[vdimid].name);
+
 	  if ( CDI_Debug )
 	    Message("gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid, ncvars[ncvarid].name);
 
@@ -5898,6 +5840,12 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
           if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive);
           if ( is_scalar ) zaxisDefScalar(ncvars[ncvarid].zaxisID);
 
+          if ( zdimid != -1 )
+            cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_DIMNAME, (int)(strlen(ncdims[zdimid].name)+1), ncdims[zdimid].name);
+          /*
+          if ( vdimid != -1 )
+            cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_VDIMNAME, strlen(ncdims[vdimid].name)+1, ncdims[vdimid].name);
+          */
 	  Free(zvar);
 	  Free(lbounds);
 	  Free(ubounds);
diff --git a/libcdi/src/stream_cgribex.c b/libcdi/src/stream_cgribex.c
index 445e4a9..474e331 100644
--- a/libcdi/src/stream_cgribex.c
+++ b/libcdi/src/stream_cgribex.c
@@ -49,20 +49,15 @@ int cgribexGetGridType(int *isec2)
     case  GRIB1_GTYPE_GME:        { gridtype = GRID_GME;      break; }
     }
 
-  return (gridtype);
+  return gridtype;
 }
 
 static
-int cgribexGetIsRotated(int *isec2)
+bool cgribexGetIsRotated(int *isec2)
 {
-  int isRotated = 0;
+  bool isRotated = (ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT) ? true : false;
 
-  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-    {
-      isRotated = 1;
-    }
-
-  return (isRotated);
+  return isRotated;
 }
 
 static
@@ -81,14 +76,14 @@ int cgribexGetZaxisHasBounds(int grb_ltype)
       }
     }
 
-  return (lbounds);
+  return lbounds;
 }
 
 static
 int cgribexGetTimeUnit(int *isec1)
 {
   int timeunit = TUNIT_HOUR;
-  static int lprint = TRUE;
+  static bool lprint = true;
 
   switch ( ISEC1_TimeUnit )
     {
@@ -104,30 +99,27 @@ int cgribexGetTimeUnit(int *isec1)
       if ( lprint )
 	{
 	  Message("GRIB time unit %d unsupported!", ISEC1_TimeUnit);
-	  lprint = FALSE;
+	  lprint = false;
 	}
       break;
     }
 
-  return (timeunit);
+  return timeunit;
 }
 
 static
-int cgribexTimeIsFC(int *isec1)
+bool cgribexTimeIsFC(int *isec1)
 {
-  int isFC = TRUE;
+  bool isFC = (ISEC1_TimeRange == 10 && ISEC1_TimePeriod1 == 0 && ISEC1_TimePeriod2 == 0) ? false : true;
 
-  if ( ISEC1_TimeRange == 10 && ISEC1_TimePeriod1 == 0 && ISEC1_TimePeriod2 == 0 )
-    isFC = FALSE;
-
-  return (isFC);
+  return isFC;
 }
 
 static
 int cgribexGetTsteptype(int timerange)
 {
   int tsteptype = TSTEP_INSTANT;
-  static int lprint = TRUE;
+  static bool lprint = true;
 
   switch ( timerange )
     {
@@ -142,18 +134,18 @@ int cgribexGetTsteptype(int timerange)
       if ( lprint )
 	{
 	  Message("Time range indicator %d unsupported, set to 0!", timerange);
-	  lprint = FALSE;
+	  lprint = false;
 	}
       break;
     }
 
-  return (tsteptype);
+  return tsteptype;
 }
 
 static
 void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4, grid_t *grid, int iret)
 {
-  int compyinc = TRUE;
+  bool compyinc = true;
   int gridtype = cgribexGetGridType(isec2);
 
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 )
@@ -164,7 +156,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
       gridtype = GRID_GAUSSIAN;
       ISEC2_NumLon = nlon;
       ISEC4_NumValues = nlon*ISEC2_NumLat;
-      compyinc = FALSE;
+      compyinc = false;
     }
 
   grid_init(grid);
@@ -187,7 +179,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
 	  {
 	    if ( grid->xsize > 1 )
 	      {
-                int recompinc = TRUE;
+                bool recompinc = true;
 
                 if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
 
@@ -195,7 +187,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
                   {
                     if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->xsize-1))) <= 2 )
                       {
-                        recompinc = FALSE;
+                        recompinc = false;
                         grid->xinc = ISEC2_LonIncr * 0.001;
                       }
                   }
@@ -224,12 +216,12 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
 	  {
 	    if ( grid->ysize > 1 && compyinc )
 	      {
-                int recompinc = TRUE;
+                bool recompinc = true;
 		if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
                   {
                     if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->ysize-1))) <= 2 )
                       {
-                        recompinc = FALSE;
+                        recompinc = false;
                         grid->yinc = ISEC2_LatIncr * 0.001;
                       }
                   }
@@ -245,13 +237,14 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
       }
     case GRID_GAUSSIAN_REDUCED:
       {
-        grid->np     = ISEC2_NumPar;
-	grid->size   = ISEC4_NumValues;
-        grid->rowlon = ISEC2_RowLonPtr;
-	grid->ysize  = ISEC2_NumLat;
-	grid->xinc   = 0;
-	grid->yinc   = 0;
-	grid->xdef   = 0;
+        grid->np      = ISEC2_NumPar;
+	grid->size    = ISEC4_NumValues;
+        grid->rowlon  = ISEC2_RowLonPtr;
+	grid->nrowlon = ISEC2_NumLat;
+	grid->ysize   = ISEC2_NumLat;
+	grid->xinc    = 0;
+	grid->yinc    = 0;
+	grid->xdef    = 0;
 	/* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
 	  {
 	    if ( grid->xsize > 1 )
@@ -362,12 +355,11 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d
 {
   int varID;
   int levelID = 0;
-  grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
 
   int vlistID = streamptr->vlistID;
   int tsID    = streamptr->curTsID;
   int recID   = recordNewEntry(streamptr, tsID);
-  record_t *record  = &streamptr->tsteps[tsID].records[recID];
+  record_t *record = &streamptr->tsteps[tsID].records[recID];
 
   int tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
   int numavg    = ISEC1_AvgNum;
@@ -385,11 +377,23 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d
   record->ltype     = ISEC1_LevelType;
   record->tsteptype = (short)tsteptype;
 
-  cgribexGetGrid(streamptr, isec2, fsec2, isec4, grid, iret);
+  grid_t *gridptr = (grid_t*) Malloc(sizeof(*gridptr));
+  cgribexGetGrid(streamptr, isec2, fsec2, isec4, gridptr, iret);
 
-  struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+  struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, gridptr, 0);
   int gridID = gridAdded.Id;
-  if (!gridAdded.isNew) Free(grid);
+  if ( gridAdded.isNew )
+    {
+      if ( gridptr->nrowlon )
+        {
+          size_t nrowlon = (size_t) gridptr->nrowlon;
+          int *rowlon = gridptr->rowlon;
+          gridptr->rowlon = (int*) Malloc(nrowlon * sizeof(int));
+          memcpy(gridptr->rowlon, rowlon, nrowlon * sizeof(int));
+        }
+    }
+  else
+    Free(gridptr);
 
   int zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
 
@@ -521,7 +525,7 @@ compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype, int tr
   compVar.ltype     = leveltype;
   compVar.tsteptype = tsteptype;
 
-  return (compVar);
+  return compVar;
 }
 
 static inline int
@@ -537,7 +541,7 @@ cgribexVarCompare(compvar_t compVar, record_t record, int flag)
     |           (compVar.level2 != record.ilevel2)
     |           (compVar.ltype != record.ltype)
     |           tstepDiff;
-  return (rstatus);
+  return rstatus;
 }
 #endif
 
@@ -594,10 +598,11 @@ int cgribexScanTimestep1(stream_t * streamptr)
   int nrecs_scanned = 0;
   int datatype;
   long recsize = 0;
-  int warn_time = TRUE;
-  int warn_numavg = TRUE;
+  bool warn_time = true;
+  bool warn_numavg = true;
   int taxisID = -1;
-  int rdate = 0, rtime = 0, tunit = 0, fcast = 0;
+  int rdate = 0, rtime = 0, tunit = 0;
+  bool fcast = false;
   int vlistID;
   int comptype;
   long unzipsize;
@@ -711,7 +716,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
 		if ( datetimeCmp(datetime, datetime0) != 0 )
 		  {
                     gribWarning("Inconsistent verification time!", nrecs_scanned, tsID+1, paramstr, level1, level2);
-		    warn_time = FALSE;
+		    warn_time = false;
 		  }
 	    }
 	  else
@@ -731,7 +736,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
 	  if (  taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
 	    {
 	      Warning("Changing numavg from %d to %d not supported!", taxis->numavg, ISEC1_AvgNum);
-	      warn_numavg = FALSE;
+	      warn_numavg = false;
 	    }
 	  else
 	    {
@@ -750,7 +755,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
 
   streamptr->rtsteps = 1;
 
-  if ( nrecs == 0 ) return (CDI_EUFSTRUCT);
+  if ( nrecs == 0 ) return CDI_EUFSTRUCT;
 
   cdi_generate_vars(streamptr);
 
@@ -794,7 +799,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
   cgribexScanTsFixNtsteps(streamptr, recpos);
   cgribexScanTsConstAdjust(streamptr, taxis);
 
-  return (0);
+  return 0;
 }
 
 
@@ -811,7 +816,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
   size_t readsize;
   int nrecs, recID;
   long recsize = 0;
-  int warn_numavg = TRUE;
+  bool warn_numavg = true;
   int tsteptype;
   long unzipsize;
   char paramstr[32];
@@ -932,7 +937,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
 	  /*
 	      Warning("Changing numavg from %d to %d not supported!", taxis->numavg, ISEC1_AvgNum);
 	  */
-	      warn_numavg = FALSE;
+	      warn_numavg = false;
 	    }
 	  else
 	    {
@@ -953,7 +958,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
       if ( recID == nrecords )
 	{
 	  gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, paramstr, level1, level2);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       if ( cdiInventoryMode == 1 )
@@ -995,7 +1000,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
 		  tsID, recID,
 		  streamptr->tsteps[tsID].records[recID].param, param,
 		  streamptr->tsteps[tsID].records[recID].ilevel, level1);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->tsteps[1].records[recID].position = recpos;
@@ -1036,7 +1041,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
   streamptr->record->buffer     = gribbuffer;
   streamptr->record->buffersize = buffersize;
 
-  return (rstatus);
+  return rstatus;
 }
 #endif
 
@@ -1056,7 +1061,7 @@ int cgribexScanTimestep(stream_t * streamptr)
   int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
   DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
   int vrecID, recID;
-  int warn_numavg = TRUE;
+  bool warn_numavg = true;
   size_t readsize;
   int taxisID = -1;
   int rindex, nrecs = 0;
@@ -1187,7 +1192,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 	      /*
 	          Warning("Changing numavg from %d to %d not supported!", streamptr->tsteps[tsID].taxis.numavg, ISEC1_AvgNum);
 	      */
-		  warn_numavg = FALSE;
+		  warn_numavg = false;
 		}
 	      else
 		{
@@ -1211,7 +1216,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 	      gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, paramstr, level1, level2);
 
 	      if ( cdiInventoryMode == 1 )
-		return (CDI_EUFSTRUCT);
+		return CDI_EUFSTRUCT;
 	      else
 		continue;
 	    }
@@ -1271,7 +1276,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 	  cdiParamToString(streamptr->tsteps[tsID].records[recID].param, paramstr, sizeof(paramstr));
 	  gribWarning("Paramameter not found!", nrecs_scanned, tsID+1, paramstr,
                       streamptr->tsteps[tsID].records[recID].ilevel, streamptr->tsteps[tsID].records[recID].ilevel2);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->rtsteps++;
@@ -1301,7 +1306,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 
   rstatus = (int)streamptr->ntsteps;
 
-  return (rstatus);
+  return rstatus;
 }
 #endif
 
@@ -1440,7 +1445,7 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
   int timerange = -1;
   int year, month, day, hour, minute, second;
   int julday1, secofday1, julday2, secofday2, days, secs;
-  int ip, ip1 = 0, ip2 = 0;
+  int ip1 = 0, ip2 = 0;
 
   cdiDecodeDate(rdate, &year, &month, &day);
   cdiDecodeTime(rtime, &hour, &minute, &second);
@@ -1454,7 +1459,9 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
 
   if ( !(int)(fmod(days*86400.0 + secs, factor)) )
     {
-      ip = (int) ((days*86400.0 + secs)/factor);
+      int ip = (int) ((days*86400.0 + secs)/factor);
+
+      if ( (ip > 255) && (tsteptype == TSTEP_INSTANT) ) tsteptype = TSTEP_INSTANT3;
 
       switch ( tsteptype )
 	{
@@ -1465,14 +1472,14 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
 	case TSTEP_ACCUM:    timerange =  4; ip1 = 0;  ip2 = ip; break;
 	case TSTEP_DIFF:     timerange =  5; ip1 = 0;  ip2 = ip; break;
 	case TSTEP_INSTANT3:
-	default:             timerange = 10; ip1 = ip/256; ip2 = ip%256;  break;
+	default:             timerange = 10; ip1 = ip/256; ip2 = ip%256; break;
 	}
     }
 
   *pip1 = ip1;
   *pip2 = ip2;
 
-  return (timerange);
+  return timerange;
 }
 
 static
@@ -1524,7 +1531,7 @@ int cgribexDefDateTime(int *isec1, int timeunit, int date, int time)
     default:              factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;      break;
     }
 
-  return (factor);
+  return factor;
 }
 
 static
@@ -1609,7 +1616,6 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg,
 static
 void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridID)
 {
-  int gridtype;
   bool lcurvi = false;
   static bool lwarning = true;
 
@@ -1617,17 +1623,15 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 
   ISEC1_Sec2Or3Flag = 128;
 
-  gridtype = gridInqType(gridID);
+  int gridtype = gridInqType(gridID);
 
   ISEC1_GridDefinition = 255;
 
   if ( gridtype == GRID_GENERIC )
     {
-      int xsize, ysize, gridsize;
-
-      gridsize = gridInqSize(gridID);
-      xsize = gridInqXsize(gridID);
-      ysize = gridInqYsize(gridID);
+      int gridsize = gridInqSize(gridID);
+      int xsize = gridInqXsize(gridID);
+      int ysize = gridInqYsize(gridID);
 
       if ( (ysize ==  32 || ysize ==  48 || ysize ==  64 ||
 	    ysize ==  96 || ysize == 160 || ysize == 192 ||
@@ -1654,7 +1658,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
       if ( lwarning && gridInqSize(gridID) > 1 )
 	{
 	  lwarning = false;
-	  Warning("Curvilinear grids are unsupported in GRIB1! Created wrong GDS!");
+	  Warning("Curvilinear grids are unsupported in GRIB1! Created wrong Grid Description Section!");
 	}
       gridtype = GRID_LONLAT;
       lcurvi = true;
@@ -1670,19 +1674,19 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
     case GRID_GAUSSIAN_REDUCED:
     case GRID_TRAJECTORY:
       {
-	int nlon = 0, nlat;
 	double xfirst = 0, xlast = 0, xinc = 0;
 	double yfirst = 0, ylast = 0, yinc = 0;
+        bool isRotated = gridIsRotated(gridID);
 
 	if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
           ISEC2_GridType = GRIB1_GTYPE_GAUSSIAN;
-        else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+        else if ( gridtype == GRID_LONLAT && isRotated )
 	  ISEC2_GridType = GRIB1_GTYPE_LATLON_ROT;
 	else
 	  ISEC2_GridType = GRIB1_GTYPE_LATLON;
 
-	nlon = gridInqXsize(gridID);
-	nlat = gridInqYsize(gridID);
+	int nlon = gridInqXsize(gridID);
+	int nlat = gridInqYsize(gridID);
 
 	if ( gridtype == GRID_GAUSSIAN_REDUCED )
 	  {
@@ -1699,10 +1703,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	    else
 	      {
 		xfirst = gridInqXval(gridID,      0);
-		if ( lcurvi )
-		  xlast  = gridInqXval(gridID, nlon*nlat-1);
-		else
-		  xlast  = gridInqXval(gridID, nlon-1);
+                xlast  = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1);
 		xinc   = gridInqXinc(gridID);
 	      }
 	  }
@@ -1714,12 +1715,8 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	else
 	  {
 	    yfirst = gridInqYval(gridID,      0);
-	    if ( lcurvi )
-	      ylast  = gridInqYval(gridID, nlon*nlat-1);
-	    else
-	      ylast  = gridInqYval(gridID, nlat-1);
-	    yinc   = gridInqYinc(gridID);
-	    if ( yinc < 0 ) yinc = -yinc;
+            ylast  = gridInqYval(gridID, (lcurvi ? nlon*nlat : nlat) - 1);
+	    yinc   = fabs(gridInqYinc(gridID));
 	  }
 
 	ISEC2_NumLon   = nlon;
@@ -1757,12 +1754,9 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
 	  if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
 
-	if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 )
-	  ISEC2_ResFlag = 0;
-	else
-	  ISEC2_ResFlag = 128;
+        ISEC2_ResFlag = ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 ) ? 0 : 128;
 
-	if ( gridIsRotated(gridID) )
+	if ( isRotated )
 	  {
 	    ISEC2_LatSP = - (int)lround(gridInqYpole(gridID) * 1000);
 	    ISEC2_LonSP =   (int)lround((gridInqXpole(gridID) + 180) * 1000);
@@ -1858,12 +1852,11 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 static
 void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int levelID)
 {
-  double level;
-  int ilevel, zaxistype, ltype;
   static bool lwarning_vct = true;
+  double level;
 
-  zaxistype = zaxisInqType(zaxisID);
-  ltype = zaxisInqLtype(zaxisID);
+  int zaxistype = zaxisInqType(zaxisID);
+  int ltype = zaxisInqLtype(zaxisID);
 
   if ( zaxistype == ZAXIS_GENERIC && ltype == 0 )
     {
@@ -1877,83 +1870,50 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
 
   ISEC2_NumVCP = 0;
 
+  int grib_ltype = zaxisTypeToGrib1ltype(zaxistype);
+
   switch (zaxistype)
     {
     case ZAXIS_SURFACE:
+    case ZAXIS_MEANSEA:
+    case ZAXIS_ALTITUDE:
+    case ZAXIS_DEPTH_BELOW_SEA:
+    case ZAXIS_ISENTROPIC:
       {
-	ISEC1_LevelType = GRIB1_LTYPE_SURFACE;
-	ISEC1_Level1    = (int)(zaxisInqLevel(zaxisID, levelID));
+        ISEC1_LevelType = grib_ltype;
+	ISEC1_Level1    = (int) (zaxisInqLevel(zaxisID, levelID));
 	ISEC1_Level2    = 0;
 	break;
       }
     case ZAXIS_CLOUD_BASE:
-      {
-	ISEC1_LevelType = GRIB1_LTYPE_CLOUD_BASE;
-	ISEC1_Level1    = 0;
-	ISEC1_Level2    = 0;
-	break;
-      }
     case ZAXIS_CLOUD_TOP:
-      {
-	ISEC1_LevelType = GRIB1_LTYPE_CLOUD_TOP;
-	ISEC1_Level1    = 0;
-	ISEC1_Level2    = 0;
-	break;
-      }
     case ZAXIS_ISOTHERM_ZERO:
-      {
-	ISEC1_LevelType = GRIB1_LTYPE_ISOTHERM0;
-	ISEC1_Level1    = 0;
-	ISEC1_Level2    = 0;
-	break;
-      }
     case ZAXIS_TOA:
-      {
-	ISEC1_LevelType = GRIB1_LTYPE_TOA;
-	ISEC1_Level1    = 0;
-	ISEC1_Level2    = 0;
-	break;
-      }
     case ZAXIS_SEA_BOTTOM:
-      {
-	ISEC1_LevelType = GRIB1_LTYPE_SEA_BOTTOM;
-	ISEC1_Level1    = 0;
-	ISEC1_Level2    = 0;
-	break;
-      }
     case ZAXIS_ATMOSPHERE:
       {
-	ISEC1_LevelType = GRIB1_LTYPE_ATMOSPHERE;
+        ISEC1_LevelType = grib_ltype;
 	ISEC1_Level1    = 0;
 	ISEC1_Level2    = 0;
 	break;
       }
-    case ZAXIS_MEANSEA:
-      {
-	ISEC1_LevelType = GRIB1_LTYPE_MEANSEA;
-	ISEC1_Level1    = (int)(zaxisInqLevel(zaxisID, levelID));
-	ISEC1_Level2    = 0;
-	break;
-      }
     case ZAXIS_HYBRID:
     case ZAXIS_HYBRID_HALF:
       {
-	int vctsize;
-
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
 	  {
 	    ISEC1_LevelType = GRIB1_LTYPE_HYBRID_LAYER;
-	    ISEC1_Level1    = (int)(zaxisInqLbound(zaxisID, levelID));
-	    ISEC1_Level2    = (int)(zaxisInqUbound(zaxisID, levelID));
+	    ISEC1_Level1    = (int) (zaxisInqLbound(zaxisID, levelID));
+	    ISEC1_Level2    = (int) (zaxisInqUbound(zaxisID, levelID));
 	  }
 	else
 	  {
 	    ISEC1_LevelType = GRIB1_LTYPE_HYBRID;
-	    ISEC1_Level1    = (int)(zaxisInqLevel(zaxisID, levelID));
+	    ISEC1_Level1    = (int) (zaxisInqLevel(zaxisID, levelID));
 	    ISEC1_Level2    = 0;
 	  }
 
-	vctsize = zaxisInqVctSize(zaxisID);
+	int vctsize = zaxisInqVctSize(zaxisID);
 	if ( vctsize > 255 )
 	  {
 	    ISEC2_NumVCP = 0;
@@ -1972,29 +1932,26 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
       }
     case ZAXIS_PRESSURE:
       {
-	double dum;
-	char units[128];
-
 	level = zaxisInqLevel(zaxisID, levelID);
 	if ( level < 0 )
 	  Warning("Pressure level of %f Pa is below zero!", level);
 
+	char units[128];
 	zaxisInqUnits(zaxisID, units);
 	if ( (units[0] != 'P') | (units[1] != 'a') ) level *= 100;
 
-	ilevel = (int) level;
+	double dum;
 	if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
 	  {
-	    ISEC1_LevelType = GRIB1_LTYPE_99;
-	    ISEC1_Level1    = ilevel;
-	    ISEC1_Level2    = 0;
+	    grib_ltype = GRIB1_LTYPE_99;
 	  }
 	else
 	  {
-	    ISEC1_LevelType = GRIB1_LTYPE_ISOBARIC;
-	    ISEC1_Level1    = ilevel/100;
-	    ISEC1_Level2    = 0;
+	    level = level/100;
 	  }
+        ISEC1_LevelType = grib_ltype;
+        ISEC1_Level1    = (int) level;
+        ISEC1_Level2    = 0;
 	break;
       }
     case ZAXIS_HEIGHT:
@@ -2010,20 +1967,8 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
             else if ( units[0] == 'k' ) level *= 1000;
           }
 
-	ilevel = (int) level;
-	ISEC1_LevelType = GRIB1_LTYPE_HEIGHT;
-	ISEC1_Level1    = ilevel;
-	ISEC1_Level2    = 0;
-
-	break;
-      }
-    case ZAXIS_ALTITUDE:
-      {
-	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
-	ISEC1_LevelType = GRIB1_LTYPE_ALTITUDE;
-	ISEC1_Level1    = ilevel;
+	ISEC1_LevelType = grib_ltype;
+	ISEC1_Level1    = (int) level;
 	ISEC1_Level2    = 0;
 
 	break;
@@ -2033,16 +1978,13 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
 	  {
 	    ISEC1_LevelType = GRIB1_LTYPE_SIGMA_LAYER;
-	    ISEC1_Level1    = (int)(zaxisInqLbound(zaxisID, levelID));
-	    ISEC1_Level2    = (int)(zaxisInqUbound(zaxisID, levelID));
+	    ISEC1_Level1    = (int) zaxisInqLbound(zaxisID, levelID);
+	    ISEC1_Level2    = (int) zaxisInqUbound(zaxisID, levelID);
 	  }
 	else
 	  {
-            level = zaxisInqLevel(zaxisID, levelID);
-
-            ilevel = (int) level;
             ISEC1_LevelType = GRIB1_LTYPE_SIGMA;
-            ISEC1_Level1    = ilevel;
+            ISEC1_Level1    = (int) zaxisInqLevel(zaxisID, levelID);
             ISEC1_Level2    = 0;
           }
 
@@ -2051,10 +1993,9 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
     case ZAXIS_DEPTH_BELOW_LAND:
       {
 	char units[128];
-	double factor;
-
 	zaxisInqUnits(zaxisID, units);
 
+	double factor;
         if      ( units[0] == 'm' && units[1] == 'm' ) factor =   0.1;
         else if ( units[0] == 'c' && units[1] == 'm' ) factor =   1;
         else if ( units[0] == 'd' && units[1] == 'm' ) factor =  10;
@@ -2062,54 +2003,23 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
 
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
 	  {
-            double level1, level2;
-            level1 = zaxisInqLbound(zaxisID, levelID);
-            level2 = zaxisInqUbound(zaxisID, levelID);
 	    ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH_LAYER;
-	    ISEC1_Level1    = (int) (level1*factor);
-	    ISEC1_Level2    = (int) (level2*factor);
+	    ISEC1_Level1    = (int) (factor*zaxisInqLbound(zaxisID, levelID));
+	    ISEC1_Level2    = (int) (factor*zaxisInqUbound(zaxisID, levelID));
 	  }
 	else
 	  {
-	    level = zaxisInqLevel(zaxisID, levelID);
-
-	    ilevel = (int) (level*factor);
 	    ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH;
-	    ISEC1_Level1    = ilevel;
+	    ISEC1_Level1    = (int) (factor*zaxisInqLevel(zaxisID, levelID));
 	    ISEC1_Level2    = 0;
 	  }
 
 	break;
       }
-    case ZAXIS_DEPTH_BELOW_SEA:
-      {
-	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
-	ISEC1_LevelType = GRIB1_LTYPE_SEADEPTH;
-	ISEC1_Level1    = ilevel;
-	ISEC1_Level2    = 0;
-
-	break;
-      }
-    case ZAXIS_ISENTROPIC:
-      {
-	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
-	ISEC1_LevelType = GRIB1_LTYPE_ISENTROPIC;
-	ISEC1_Level1    = ilevel;
-	ISEC1_Level2    = 0;
-
-	break;
-      }
     case ZAXIS_GENERIC:
       {
-	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
 	ISEC1_LevelType = ltype;
-	ISEC1_Level1    = ilevel;
+	ISEC1_Level1    = (int) zaxisInqLevel(zaxisID, levelID);
 	ISEC1_Level2    = 0;
 
 	break;
diff --git a/libcdi/src/stream_grb.c b/libcdi/src/stream_grb.c
index a56313a..3900e8a 100644
--- a/libcdi/src/stream_grb.c
+++ b/libcdi/src/stream_grb.c
@@ -93,23 +93,31 @@ int zaxisTypeToGrib1ltype(int zaxistype)
   switch (zaxistype)
     {
     case ZAXIS_SURFACE:               grib_ltype = GRIB1_LTYPE_SURFACE;            break;
-    case ZAXIS_MEANSEA:               grib_ltype = GRIB1_LTYPE_MEANSEA;            break;
+    case ZAXIS_GENERIC:               grib_ltype = -1;                             break;
+    case ZAXIS_HYBRID:                grib_ltype = -1;                             break;
+    case ZAXIS_HYBRID_HALF:           grib_ltype = -1;                             break;
+    case ZAXIS_PRESSURE:              grib_ltype = GRIB1_LTYPE_ISOBARIC;           break;
     case ZAXIS_HEIGHT:                grib_ltype = GRIB1_LTYPE_HEIGHT;             break;
-    case ZAXIS_ALTITUDE:              grib_ltype = GRIB1_LTYPE_ALTITUDE;           break;
-    case ZAXIS_SIGMA:                 grib_ltype = GRIB1_LTYPE_SIGMA;              break;
     case ZAXIS_DEPTH_BELOW_SEA:       grib_ltype = GRIB1_LTYPE_SEADEPTH;           break;
+    case ZAXIS_DEPTH_BELOW_LAND:      grib_ltype = GRIB1_LTYPE_LANDDEPTH;          break;
     case ZAXIS_ISENTROPIC:            grib_ltype = GRIB1_LTYPE_ISENTROPIC;         break;
+    case ZAXIS_TRAJECTORY:            grib_ltype = -1;                             break;
+    case ZAXIS_ALTITUDE:              grib_ltype = GRIB1_LTYPE_ALTITUDE;           break;
+    case ZAXIS_SIGMA:                 grib_ltype = GRIB1_LTYPE_SIGMA;              break;
+    case ZAXIS_MEANSEA:               grib_ltype = GRIB1_LTYPE_MEANSEA;            break;
+    case ZAXIS_TOA:                   grib_ltype = GRIB1_LTYPE_TOA;                break;
+    case ZAXIS_SEA_BOTTOM:            grib_ltype = GRIB1_LTYPE_SEA_BOTTOM;         break;
+    case ZAXIS_ATMOSPHERE:            grib_ltype = GRIB1_LTYPE_ATMOSPHERE;         break;
     case ZAXIS_CLOUD_BASE:            grib_ltype = GRIB1_LTYPE_CLOUD_BASE;         break;
     case ZAXIS_CLOUD_TOP:             grib_ltype = GRIB1_LTYPE_CLOUD_TOP;          break;
     case ZAXIS_ISOTHERM_ZERO:         grib_ltype = GRIB1_LTYPE_ISOTHERM0;          break;
-    case ZAXIS_TOA:                   grib_ltype = GRIB1_LTYPE_TOA;                break;
-    case ZAXIS_SEA_BOTTOM:            grib_ltype = GRIB1_LTYPE_SEA_BOTTOM;         break;
+    case ZAXIS_SNOW:                  grib_ltype = -1;                             break;
     case ZAXIS_LAKE_BOTTOM:           grib_ltype = GRIB1_LTYPE_LAKE_BOTTOM;        break;
     case ZAXIS_SEDIMENT_BOTTOM:       grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM;    break;
     case ZAXIS_SEDIMENT_BOTTOM_TA:    grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TA; break;
     case ZAXIS_SEDIMENT_BOTTOM_TW:    grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TW; break;
     case ZAXIS_MIX_LAYER:             grib_ltype = GRIB1_LTYPE_MIX_LAYER;          break;
-    case ZAXIS_ATMOSPHERE:            grib_ltype = GRIB1_LTYPE_ATMOSPHERE;         break;
+    case ZAXIS_REFERENCE:             grib_ltype = -1;                             break;
     }
 
   return grib_ltype;
@@ -123,23 +131,31 @@ int zaxisTypeToGrib2ltype(int zaxistype)
   switch (zaxistype)
     {
     case ZAXIS_SURFACE:               grib_ltype = GRIB2_LTYPE_SURFACE;            break;
-    case ZAXIS_MEANSEA:               grib_ltype = GRIB2_LTYPE_MEANSEA;            break;
+    case ZAXIS_GENERIC:               grib_ltype = -1;                             break;
+    case ZAXIS_HYBRID:                grib_ltype = GRIB2_LTYPE_HYBRID;             break;
+    case ZAXIS_HYBRID_HALF:           grib_ltype = GRIB2_LTYPE_HYBRID;             break;
+    case ZAXIS_PRESSURE:              grib_ltype = GRIB2_LTYPE_ISOBARIC;           break;
     case ZAXIS_HEIGHT:                grib_ltype = GRIB2_LTYPE_HEIGHT;             break;
-    case ZAXIS_ALTITUDE:              grib_ltype = GRIB2_LTYPE_ALTITUDE;           break;
-    case ZAXIS_SIGMA:                 grib_ltype = GRIB2_LTYPE_SIGMA;              break;
     case ZAXIS_DEPTH_BELOW_SEA:       grib_ltype = GRIB2_LTYPE_SEADEPTH;           break;
+    case ZAXIS_DEPTH_BELOW_LAND:      grib_ltype = GRIB2_LTYPE_LANDDEPTH;          break;
     case ZAXIS_ISENTROPIC:            grib_ltype = GRIB2_LTYPE_ISENTROPIC;         break;
+    case ZAXIS_TRAJECTORY:            grib_ltype = -1;                             break;
+    case ZAXIS_ALTITUDE:              grib_ltype = GRIB2_LTYPE_ALTITUDE;           break;
+    case ZAXIS_SIGMA:                 grib_ltype = GRIB2_LTYPE_SIGMA;              break;
+    case ZAXIS_MEANSEA:               grib_ltype = GRIB2_LTYPE_MEANSEA;            break;
+    case ZAXIS_TOA:                   grib_ltype = GRIB2_LTYPE_TOA;                break;
+    case ZAXIS_SEA_BOTTOM:            grib_ltype = GRIB2_LTYPE_SEA_BOTTOM;         break;
+    case ZAXIS_ATMOSPHERE:            grib_ltype = GRIB2_LTYPE_ATMOSPHERE;         break;
     case ZAXIS_CLOUD_BASE:            grib_ltype = GRIB2_LTYPE_CLOUD_BASE;         break;
     case ZAXIS_CLOUD_TOP:             grib_ltype = GRIB2_LTYPE_CLOUD_TOP;          break;
     case ZAXIS_ISOTHERM_ZERO:         grib_ltype = GRIB2_LTYPE_ISOTHERM0;          break;
-    case ZAXIS_TOA:                   grib_ltype = GRIB2_LTYPE_TOA;                break;
-    case ZAXIS_SEA_BOTTOM:            grib_ltype = GRIB2_LTYPE_SEA_BOTTOM;         break;
+    case ZAXIS_SNOW:                  grib_ltype = GRIB2_LTYPE_SNOW;               break;
     case ZAXIS_LAKE_BOTTOM:           grib_ltype = GRIB2_LTYPE_LAKE_BOTTOM;        break;
     case ZAXIS_SEDIMENT_BOTTOM:       grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM;    break;
     case ZAXIS_SEDIMENT_BOTTOM_TA:    grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TA; break;
     case ZAXIS_SEDIMENT_BOTTOM_TW:    grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TW; break;
     case ZAXIS_MIX_LAYER:             grib_ltype = GRIB2_LTYPE_MIX_LAYER;          break;
-    case ZAXIS_ATMOSPHERE:            grib_ltype = GRIB2_LTYPE_ATMOSPHERE;         break;
+    case ZAXIS_REFERENCE:             grib_ltype = GRIB2_LTYPE_REFERENCE;          break;
     }
 
   return grib_ltype;
diff --git a/libcdi/src/stream_gribapi.c b/libcdi/src/stream_gribapi.c
index 737bc88..8189a76 100644
--- a/libcdi/src/stream_gribapi.c
+++ b/libcdi/src/stream_gribapi.c
@@ -56,7 +56,7 @@ int gribapiGetZaxisType(long editionNumber, int grib_ltype)
       zaxistype = grib2ltypeToZaxisType(grib_ltype);
     }
 
-  return (zaxistype);
+  return zaxistype;
 }
 
 static
@@ -76,7 +76,7 @@ int getTimeunits(long unitsOfTime)
     default:  timeunits = TUNIT_HOUR;    break;
     }
 
-  return (timeunits);
+  return timeunits;
 }
 
 static
@@ -98,7 +98,7 @@ double timeunit_factor(int tu1, int tu2)
         }
     }
 
-  return (factor);
+  return factor;
 }
 
 static
@@ -113,7 +113,7 @@ int gribapiGetTimeUnits(grib_handle *gh)
 
   timeunits = getTimeunits(unitsOfTime);
 
-  return (timeunits);
+  return timeunits;
 }
 
 static
@@ -241,7 +241,7 @@ int gribapiGetValidityDateTime(grib_handle *gh, int *vdate, int *vtime)
       }
     }
 
-  return (tstepRange);
+  return tstepRange;
 }
 
 static
@@ -253,7 +253,7 @@ void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
   *level2    = 0;
 
   long lpar;
-  if(!grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar))       //1 byte
+  if ( !grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar) )       //1 byte
     {
       *leveltype = (int) lpar;
 
@@ -644,7 +644,7 @@ static compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype
   memcpy(compVar.name, name, len);
   compVar.tiles = tiles_data;
 
-  return (compVar);
+  return compVar;
 }
 
 static
@@ -682,7 +682,7 @@ void ensureBufferSize(size_t requiredSize, size_t *curSize, void **buffer)
 static
 grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, void **gribbuffer, int *outDatatype, int *outCompressionType, long *outUnzipsize)
 {
-  int lieee = FALSE;
+  bool lieee = false;
 
   grib_handle *gh = grib_handle_new_from_message(NULL, *gribbuffer, recsize);
   if(gribEditionNumber(gh) > 1)
@@ -695,7 +695,7 @@ grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, vo
           // fprintf(stderr, "packingType %d %s\n", len, typeOfPacking);
           if      ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) *outCompressionType = COMPRESS_JPEG;
           else if ( strncmp(typeOfPacking, "grid_ccsds", len) == 0 ) *outCompressionType = COMPRESS_SZIP;
-          else if ( strncmp(typeOfPacking, "grid_ieee", len) == 0 ) lieee = TRUE;
+          else if ( strncmp(typeOfPacking, "grid_ieee", len) == 0 ) lieee = true;
         }
     }
   else
@@ -901,7 +901,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
   streamptr->rtsteps = 1;
 
-  if ( nrecs == 0 ) return (CDI_EUFSTRUCT);
+  if ( nrecs == 0 ) return CDI_EUFSTRUCT;
 
   cdi_generate_vars(streamptr);
 
@@ -964,7 +964,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
         }
     }
 
-  return (0);
+  return 0;
 }
 
 
@@ -1097,7 +1097,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
       if ( recID == nrecords )
 	{
 	  gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       if ( streamptr->tsteps[tsID].records[recID].used )
@@ -1131,7 +1131,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 		  tsID, recID,
 		  streamptr->tsteps[tsID].records[recID].param, param,
 		  streamptr->tsteps[tsID].records[recID].ilevel, level1);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->tsteps[1].records[recID].position = recpos;
@@ -1186,7 +1186,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
   streamptr->record->buffer     = gribbuffer;
   streamptr->record->buffersize = buffersize;
 
-  return (rstatus);
+  return rstatus;
 }
 
 
@@ -1332,7 +1332,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	      gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
 
 	      if ( cdiInventoryMode == 1 )
-		return (CDI_EUFSTRUCT);
+		return CDI_EUFSTRUCT;
 	      else
 		continue;
 	    }
@@ -1389,7 +1389,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	{
 	  gribWarning("Paramameter not found!", nrecs_scanned, tsID+1, varname, streamptr->tsteps[tsID].records[recID].param,
                       streamptr->tsteps[tsID].records[recID].ilevel, streamptr->tsteps[tsID].records[recID].ilevel2);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->rtsteps++;
@@ -1437,11 +1437,11 @@ int gribapiDecode(void *gribbuffer, int gribsize, double *data, long gridsize,
 
   if ( unreduced )
     {
-      static int lwarn = 1;
+      static bool lwarn = true;
 
       if ( lwarn )
 	{
-	  lwarn = 0;
+	  lwarn = false;
 	  Warning("Conversion of gaussian reduced grids unsupported!");
 	}
     }
@@ -1602,11 +1602,42 @@ int getTimeunitFactor(int timeunit)
     default:            factor =  3600;  break;
     }
 
-  return (factor);
+  return factor;
 }
 
 static
-void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
+int grib2ProDefTempHasStatisticalDef(int proDefTempNum)
+{
+  int hasStatisticalDef = 0;
+
+  switch (proDefTempNum)
+    {
+      case 8:
+      case 9:
+      case 10:
+      case 11:
+      case 12:
+      case 13:
+      case 14:
+      case 34:
+      case 42:
+      case 43:
+      case 46:
+      case 47:
+      case 61:
+      case 91:
+      case 1001:
+      case 1101:
+      case 40034:
+               hasStatisticalDef = 1;  break;
+      default: hasStatisticalDef = 0;  break;
+    }
+
+  return hasStatisticalDef;
+}
+
+static
+void gribapiDefStepUnits(int editionNumber, grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
 {
   long unitsOfTime;
 
@@ -1625,9 +1656,19 @@ void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int g
   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);
+      if ( editionNumber == 1 )
+        {
+          GRIB_CHECK(my_grib_set_long(gh, "unitOfTimeRange", unitsOfTime), 0);
+        }
+      else if ( grib2ProDefTempHasStatisticalDef(proDefTempNum) )
+        {
+          GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0);
+          //  GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+        }
+      else
+        {
+          GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+        }
     }
 }
 
@@ -1679,7 +1720,7 @@ int gribapiDefSteptype(int editionNumber, grib_handle *gh, int productDefinition
       GRIB_CHECK(my_grib_set_string(gh, "stepType", stepType, &len), 0);
     }
 
-  return ((int)proDefTempNum);
+  return (int)proDefTempNum;
 }
 
 static
@@ -1721,7 +1762,7 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
     {
       int proDefTempNum = gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
 
-      gribapiDefStepUnits(gh, timeunit, proDefTempNum, gcinit);
+      gribapiDefStepUnits(editionNumber, gh, timeunit, proDefTempNum, gcinit);
 
       endStep = (int) ((days*86400.0 + secs)/factor);
 
@@ -1745,7 +1786,7 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
       status = 0;
     }
 
-  return (status);
+  return status;
 }
 
 static
@@ -1790,12 +1831,43 @@ void gribapiDefTime(int editionNumber, int productDefinitionTemplate, int typeOf
     }
 }
 
-static
-void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, int lieee, int datatype, int nmiss, int gcinit)
+struct gribApiMsg {
+  size_t msgLen;
+  const char *msg;
+};
+
+static struct gribApiMsg
+getGribApiCompTypeMsg(grib_handle *gh, int comptype, int gridsize)
 {
-  int status;
-  static short lwarn = TRUE;
+  const char *mesg;
+  size_t len;
+
+  if ( comptype == COMPRESS_JPEG && gridsize > 1 )
+    {
+      static const char mesg_grid_jpeg[] = "grid_jpeg";
+      len = sizeof (mesg_grid_jpeg) - 1;
+      mesg = mesg_grid_jpeg;
+    }
+  else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
+    {
+      static const char mesg_grid_ccsds[] = "grid_ccsds";
+      len = sizeof (mesg_grid_ccsds) - 1;
+      mesg = mesg_grid_ccsds;
+    }
+  else
+    {
+      static const char mesg_simple[] = "grid_simple";
+      len = sizeof (mesg_simple) - 1;
+      mesg = mesg_simple;
+    }
+
+  return (struct gribApiMsg){ .msgLen = len, .msg = mesg };
+}
 
+
+static
+void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, bool lieee, int datatype, int nmiss, int gcinit)
+{
   UNUSED(nmiss);
 
   int gridtype = gridInqType(gridID);
@@ -1832,10 +1904,11 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
     }
   else if ( gridtype == GRID_CURVILINEAR )
     {
+      static bool lwarn = true;
       if ( lwarn && gridsize > 1 )
 	{
-	  lwarn = FALSE;
-	  Warning("Curvilinear grids are unsupported in GRIB format! Created wrong GDS!");
+	  lwarn = false;
+	  Warning("Curvilinear grids are unsupported in GRIB format! Created wrong Grid Description Section!");
 	}
       gridtype = GRID_LONLAT;
     }
@@ -1846,24 +1919,11 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 
       if ( comptype )
         {
-          if ( comptype == COMPRESS_JPEG && gridsize > 1 )
-            {
-              static const char mesg[] = "grid_jpeg";
-              size_t len = sizeof (mesg) - 1;
-              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-            }
-          else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
-            {
-              static const char mesg[] = "grid_ccsds";
-              size_t len = sizeof (mesg) - 1;
-              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-            }
-          else
-            {
-              static const char mesg[] = "grid_simple";
-              size_t len = sizeof (mesg) - 1;
-              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-            }
+          struct gribApiMsg gaMsg
+            = getGribApiCompTypeMsg(gh, comptype, gridsize);
+          size_t len = gaMsg.msgLen;
+          const char *mesg = gaMsg.msg;
+          GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
         }
     }
 
@@ -1880,50 +1940,58 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	double yfirst = 0, ylast = 0, yinc = 0;
 	double latIncr;
 
-	if ( gridtype == GRID_GAUSSIAN )
-	  {
-            static const char mesg[] = "regular_gg";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-	  }
-	else if ( gridtype == GRID_GAUSSIAN_REDUCED )
-	  {
-            static const char mesg[] = "reduced_gg";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-	  }
-	else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
-	  {
-            static const char mesg[] = "rotated_ll";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-	  }
-	else
-	  {
-            static const char mesg[] = "regular_ll";
-            size_t len = sizeof (mesg) -1;
-	    GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+        {
+          const char *mesg;
+          size_t len;
+          if ( gridtype == GRID_GAUSSIAN )
+            {
+              static const char mesg_gaussian[] = "regular_gg";
+              len = sizeof (mesg_gaussian) - 1;
+              mesg = mesg_gaussian;
+            }
+          else if ( gridtype == GRID_GAUSSIAN_REDUCED )
+            {
+              static const char mesg_gaussian_reduced[] = "reduced_gg";
+              len = sizeof (mesg_gaussian_reduced) - 1;
+              mesg = mesg_gaussian_reduced;
+            }
+          else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+            {
+              static const char mesg_rot_lonlat[] = "rotated_ll";
+              len = sizeof (mesg_rot_lonlat) - 1;
+              mesg = mesg_rot_lonlat;
+            }
+          else
+            {
+              static const char mesg_regular_ll[] = "regular_ll";
+              len = sizeof (mesg_regular_ll) - 1;
+              mesg = mesg_regular_ll;
 	  }
+          GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+        }
 
-	int nlon = gridInqXsize(gridID);
-	int nlat = gridInqYsize(gridID);
+	long nlon = gridInqXsize(gridID);
+	long nlat = gridInqYsize(gridID);
 
 	if ( gridtype == GRID_GAUSSIAN_REDUCED )
 	  {
-	    int *rowlon, i;
-	    long *pl = NULL;
+            //GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridsize), 0);
 
 	    nlon = 0;
 
-	    rowlon = (int *) Malloc((size_t)nlat*sizeof(int));
-	    pl     = (long *) Malloc((size_t)nlat*sizeof(long));
+	    int *rowlon = (int *) Malloc((size_t)nlat*sizeof(int));
+	    long *pl    = (long *) Malloc((size_t)nlat*sizeof(long));
 	    gridInqRowlon(gridID, rowlon);
-	    for ( i = 0; i < nlat; ++i ) pl[i] = rowlon[i];
+	    for ( int i = 0; i < nlat; ++i ) pl[i] = rowlon[i];
 
-	    // GRIB_CHECK(my_grib_set_long_array(gh, "pl", pl, nlat), 0);
+            GRIB_CHECK(grib_set_long_array(gh, "pl", pl, nlat), 0);
 
 	    Free(pl);
 	    Free(rowlon);
+
+	    xfirst = 0;
+	    xlast  = 360.-360./(nlat*2);
+	    xinc   = 360./(nlat*2);
 	  }
 	else
 	  {
@@ -1950,13 +2018,14 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	    yinc   = gridInqYinc(gridID);
 	  }
 
-	GRIB_CHECK(my_grib_set_long(gh, "Ni", nlon), 0);
-	GRIB_CHECK(my_grib_set_long(gh, "Nj", nlat), 0);
+	if ( gridtype != GRID_GAUSSIAN_REDUCED ) GRIB_CHECK(my_grib_set_long(gh, "Ni", nlon), 0);
 	GRIB_CHECK(my_grib_set_double(gh, "longitudeOfFirstGridPointInDegrees", xfirst), 0);
 	GRIB_CHECK(my_grib_set_double(gh, "longitudeOfLastGridPointInDegrees",  xlast), 0);
+	GRIB_CHECK(my_grib_set_double(gh, "iDirectionIncrementInDegrees", xinc), 0);
+
+	GRIB_CHECK(my_grib_set_long(gh, "Nj", nlat), 0);
 	GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees",  yfirst), 0);
 	GRIB_CHECK(my_grib_set_double(gh, "latitudeOfLastGridPointInDegrees",   ylast), 0);
-	GRIB_CHECK(my_grib_set_double(gh, "iDirectionIncrementInDegrees", xinc), 0);
 
         {
           long jscan = 0;
@@ -2015,40 +2084,30 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	/* South -> North */
 	//if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
 
-        if ( editionNumber != 2 ) { lieee = 0; comptype = 0; }
+        if ( editionNumber != 2 ) { lieee = false; comptype = 0; }
 
-        if ( lieee )
-          {
-            static const char mesg[] = "grid_ieee";
-            size_t len = sizeof (mesg) -1;
-            GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+        {
+          const char *mesg;
+          size_t len;
+          if ( lieee )
+            {
+              static const char mesg_grid_ieee[] = "grid_ieee";
+              len = sizeof (mesg_grid_ieee) - 1;
+              mesg = mesg_grid_ieee;
+            }
+          else
+            {
+              struct gribApiMsg gaMsg
+                = getGribApiCompTypeMsg(gh, comptype, gridsize);
+              len = gaMsg.msgLen;
+              mesg = gaMsg.msg;
+            }
+          GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+          if ( lieee )
+            GRIB_CHECK(my_grib_set_long(gh, "precision",
+                                        datatype == DATATYPE_FLT64 ? 2 : 1), 0);
 
-	    if ( datatype == DATATYPE_FLT64 )
-	      GRIB_CHECK(my_grib_set_long(gh, "precision", 2), 0);
-	    else
-	      GRIB_CHECK(my_grib_set_long(gh, "precision", 1), 0);
-          }
-        else
-	  {
-            if ( comptype == COMPRESS_JPEG && gridsize > 1 )
-              {
-                static const char mesg[] = "grid_jpeg";
-                size_t len = sizeof (mesg) -1;
-                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-              }
-            else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
-              {
-                static const char mesg[] = "grid_ccsds";
-                size_t len = sizeof (mesg) -1;
-                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-              }
-            else
-              {
-                static const char mesg[] = "grid_simple";
-                size_t len = sizeof (mesg) -1;
-                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-              }
-	  }
+        }
 
 	break;
       }
@@ -2090,12 +2149,11 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
       }
     case GRID_SPECTRAL:
       {
-	int trunc = gridInqTrunc(gridID);
-
         static const char mesg[] = "sh";
         size_t len = sizeof (mesg) -1;
 	GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
 
+	int trunc = gridInqTrunc(gridID);
 	GRIB_CHECK(my_grib_set_long(gh, "J", trunc), 0);
 	GRIB_CHECK(my_grib_set_long(gh, "K", trunc), 0);
 	GRIB_CHECK(my_grib_set_long(gh, "M", trunc), 0);
@@ -2155,12 +2213,12 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
       }
     case GRID_UNSTRUCTURED:
       {
-	static int warning = 1;
+	static bool warning = true;
 
-	status = my_grib_set_long(gh, "gridDefinitionTemplateNumber", GRIB2_GTYPE_UNSTRUCTURED);
+	int status = my_grib_set_long(gh, "gridDefinitionTemplateNumber", GRIB2_GTYPE_UNSTRUCTURED);
 	if ( status != 0 && warning )
 	  {
-	    warning = 0;
+	    warning = false;
 	    Warning("Can't write reference grid!");
 	    Warning("gridDefinitionTemplateNumber %d not found (grib2/template.3.%d.def)!",
 		    GRIB2_GTYPE_UNSTRUCTURED, GRIB2_GTYPE_UNSTRUCTURED);
@@ -2220,20 +2278,40 @@ void getLevelFactor(double level, long *factor, long *out_scaled_value)
 static
 void gribapiDefLevelType(grib_handle *gh, int gcinit, const char *keyname, long leveltype)
 {
-  if ( !gcinit ) GRIB_CHECK(my_grib_set_long(gh, keyname, leveltype), 0);
+  bool lset = false;
+  if ( (leveltype == 99 || leveltype == 100) && gribEditionNumber(gh) == 1 )
+    {
+      if ( gribGetLong(gh, "indicatorOfTypeOfLevel") != leveltype ) lset = true;
+    }
+
+  if ( !gcinit || lset ) GRIB_CHECK(my_grib_set_long(gh, keyname, leveltype), 0);
 }
 
 static
-void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype1, long leveltype2, int lbounds, double level, double dlevel1, double dlevel2)
+void grib1DefLevel(grib_handle *gh, int gcinit, long leveltype, bool lbounds, double level, double dlevel1, double dlevel2)
 {
-  long scaled_level;
-  long factor;
+  gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", leveltype);
+
+  if ( lbounds )
+    {
+      GRIB_CHECK(my_grib_set_long(gh, "topLevel", lround(dlevel1)), 0);
+      GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", lround(dlevel2)), 0);
+    }
+  else
+    {
+      GRIB_CHECK(my_grib_set_long(gh, "level", lround(level)), 0);
+    }
+}
 
+static
+void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype1, long leveltype2, bool lbounds, double level, double dlevel1, double dlevel2)
+{
   gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", leveltype1);
   if ( lbounds ) gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", leveltype2);
 
   if ( !lbounds ) dlevel1 = level;
 
+  long scaled_level, factor;
   getLevelFactor(dlevel1, &factor, &scaled_level);
   GRIB_CHECK(my_grib_set_long(gh, "scaleFactorOfFirstFixedSurface", factor), 0);
   GRIB_CHECK(my_grib_set_long(gh, "scaledValueOfFirstFixedSurface", scaled_level), 0);
@@ -2246,20 +2324,38 @@ void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype1, long leveltype2
     }
 }
 
+
+/*
+void grib_verfiy_zaxis(int zaxisID, double sf)
+{
+  printf("grb_verfiy_vlist called\n");
+  int zaxisID = vlistZaxis(vlistID, index);
+  int nlevels = zaxisInqSize(zaxisID);
+  int zaxistype = zaxisInqType(zaxisID);
+  double *levels = (double *) Malloc(nlevels*sizeof(double));
+  int *ilevels = (int *) Malloc(nlevels*sizeof(int));
+  zaxisInqLevels(zaxisID, levels);
+  for ( int i = 0; i < nlevels; ++i )
+    printf("level %d %g\n", i+1, levels[i]);
+  Free(ilevels);
+  Free(levels);
+}
+*/
+
 static
 void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID, int levelID, int gcinit, int proddef_template_num)
 {
-  int lbounds = 0;
+  bool lbounds = false;
   double dlevel1 = 0, dlevel2 = 0;
 
   int zaxistype = zaxisInqType(zaxisID);
-  int ltype = zaxisInqLtype(zaxisID);
-  int ltype2 = zaxisInqLtype2(zaxisID);
+  long ltype = zaxisInqLtype(zaxisID);
+  long ltype2 = zaxisInqLtype2(zaxisID);
   double level = zaxisInqLevel(zaxisID, levelID);
 
   if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
     {
-      lbounds = 1;
+      lbounds = true;
       dlevel1 = zaxisInqLbound(zaxisID, levelID);
       dlevel2 = zaxisInqUbound(zaxisID, levelID);
     }
@@ -2277,7 +2373,11 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
       zaxisDefUnits(zaxisID, "Pa");
     }
 
-  int grib2ltype = zaxisTypeToGrib2ltype(zaxistype);
+  long grib_ltype = -1;
+  if ( editionNumber <= 1 )
+    grib_ltype = zaxisTypeToGrib1ltype(zaxistype);
+  else
+    grib_ltype = zaxisTypeToGrib2ltype(zaxistype);
 
   switch (zaxistype)
     {
@@ -2310,8 +2410,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 
         if ( editionNumber <= 1 )
           {
-            gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", zaxisTypeToGrib1ltype(zaxistype));
-            GRIB_CHECK(my_grib_set_long(gh, "level", (long)level), 0);
+            grib1DefLevel(gh, gcinit, grib_ltype, lbounds, level, dlevel1, dlevel2);
           }
         else
           {
@@ -2323,7 +2422,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
                The key/value pairs that are set in "grib2DefLevel" do not exist for this template.
             */
             if ( proddef_template_num != 32 )
-              grib2DefLevel(gh, gcinit, grib2ltype, grib2ltype, lbounds, level, dlevel1, dlevel2);
+              grib2DefLevel(gh, gcinit, grib_ltype, grib_ltype, lbounds, level, dlevel1, dlevel2);
           }
 
 	break;
@@ -2342,20 +2441,11 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
       {
         if ( editionNumber <= 1 )
           {
-            gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", zaxisTypeToGrib1ltype(zaxistype));
-            if ( lbounds )
-              {
-                GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
-                GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
-              }
-            else
-              {
-                GRIB_CHECK(my_grib_set_long(gh, "level", (long) level), 0);
-              }
+            grib1DefLevel(gh, gcinit, grib_ltype, lbounds, level, dlevel1, dlevel2);
           }
         else
           {
-            grib2DefLevel(gh, gcinit, grib2ltype, grib2ltype, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, grib_ltype, grib_ltype, lbounds, level, dlevel1, dlevel2);
           }
 
         break;
@@ -2365,21 +2455,12 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
       {
         if ( editionNumber <= 1 )
           {
-            if ( lbounds )
-              {
-                gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_HYBRID_LAYER);
-                GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
-                GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
-              }
-            else
-              {
-                gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_HYBRID);
-                GRIB_CHECK(my_grib_set_long(gh, "level", (long) level), 0);
-              }
+            grib_ltype = lbounds ? GRIB1_LTYPE_HYBRID_LAYER : GRIB1_LTYPE_HYBRID;
+            grib1DefLevel(gh, gcinit, grib_ltype, lbounds, level, dlevel1, dlevel2);
           }
         else
           {
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_HYBRID, GRIB2_LTYPE_HYBRID, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, grib_ltype, grib_ltype, lbounds, level, dlevel1, dlevel2);
           }
 
         if ( !gcinit )
@@ -2396,11 +2477,9 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
       }
     case ZAXIS_PRESSURE:
       {
-	double dum;
-	char units[128];
-
 	if ( level < 0 ) Warning("Pressure level of %f Pa is below zero!", level);
 
+	char units[128];
 	zaxisInqUnits(zaxisID, units);
 	if ( memcmp(units, "Pa", 2) != 0 )
           {
@@ -2411,15 +2490,13 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 
         if ( editionNumber <= 1 )
           {
-            long leveltype = GRIB1_LTYPE_ISOBARIC;
-
+            double dum;
             if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
-              leveltype = GRIB1_LTYPE_99;
+              grib_ltype = GRIB1_LTYPE_99;
             else
               level /= 100;
 
-            gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", leveltype);
-            GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
+            grib1DefLevel(gh, gcinit, grib_ltype, lbounds, level, dlevel1, dlevel2);
 	  }
 	else
 	  {
@@ -2435,7 +2512,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
           ; // not available
 	else
           {
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_SNOW, GRIB2_LTYPE_SNOW, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, grib_ltype, grib_ltype, lbounds, level, dlevel1, dlevel2);
           }
 
 	break;
@@ -2443,87 +2520,58 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
     case ZAXIS_DEPTH_BELOW_LAND:
       {
 	char units[128];
-
 	zaxisInqUnits(zaxisID, units);
+        double sf; //scalefactor
 
 	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;
-	    else                                    scalefactor = 100;
-
-	    gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_LANDDEPTH);
-	    GRIB_CHECK(my_grib_set_double(gh, "level", level*scalefactor), 0);
+	    if      ( memcmp(units, "mm", 2) == 0 ) sf =   0.1;
+	    else if ( memcmp(units, "cm", 2) == 0 ) sf =   1; // cm
+	    else if ( memcmp(units, "dm", 2) == 0 ) sf =  10;
+	    else                                    sf = 100;
+
+            grib1DefLevel(gh, gcinit, grib_ltype, lbounds, level*sf, dlevel1*sf, dlevel2*sf);
 	  }
 	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;
-	    else                                    scalefactor = 1; // meter
+	    if      ( memcmp(units, "mm", 2) == 0 ) sf = 0.001;
+	    else if ( memcmp(units, "cm", 2) == 0 ) sf = 0.01;
+	    else if ( memcmp(units, "dm", 2) == 0 ) sf = 0.1;
+	    else                                    sf = 1; // meter
 
-            level   *= scalefactor;
-            dlevel1 *= scalefactor;
-            dlevel2 *= scalefactor;
-
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_LANDDEPTH, GRIB2_LTYPE_LANDDEPTH, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, grib_ltype, grib_ltype, lbounds, level*sf, dlevel1*sf, dlevel2*sf);
 	  }
 
 	break;
       }
     case ZAXIS_REFERENCE:
       {
-        unsigned char uuid[CDI_UUID_SIZE];
+        if ( !gcinit ) GRIB_CHECK(my_grib_set_long(gh, "genVertHeightCoords", 1), 0);
 
-        if ( !gcinit )
-          {
-            GRIB_CHECK(my_grib_set_long(gh, "genVertHeightCoords", 1), 0);
-          }
-
-        if ( lbounds )
+        if ( editionNumber <= 1 )
+          ; // not available
+        else
           {
-            if ( editionNumber <= 1 )
-              ; // not available
-            else
+            if ( lbounds )
               {
-                int number = zaxisInqNumber(zaxisID);
-                gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", GRIB2_LTYPE_REFERENCE);
-                gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", GRIB2_LTYPE_REFERENCE);
-                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);
-                size_t len = CDI_UUID_SIZE;
-                zaxisInqUUID(zaxisID, uuid);
-                if (grib_set_bytes(gh, "uuidOfVGrid", uuid, &len) != 0)
-                  {
-                    Warning("Can't write UUID!");
-                  }
+                gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", grib_ltype);
+                gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", grib_ltype);
                 GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
               }
-          }
-        else
-          {
-            if ( editionNumber <= 1 )
-              ; // not available
             else
               {
-                int number = zaxisInqNumber(zaxisID);
-                gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", GRIB2_LTYPE_REFERENCE);
-                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);
-                size_t len = CDI_UUID_SIZE;
-                zaxisInqUUID(zaxisID, uuid);
-                if (grib_set_bytes(gh, "uuidOfVGrid", uuid, &len) != 0)
-                  {
-                    Warning("Can't write UUID!");
-                  }
-                GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
+                grib2DefLevel(gh, gcinit, GRIB2_LTYPE_REFERENCE, GRIB2_LTYPE_REFERENCE, lbounds, level, dlevel1, dlevel2);
               }
+
+            int number = zaxisInqNumber(zaxisID);
+            unsigned char uuid[CDI_UUID_SIZE];
+            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);
+            size_t len = CDI_UUID_SIZE;
+            zaxisInqUUID(zaxisID, uuid);
+            if ( grib_set_bytes(gh, "uuidOfVGrid", uuid, &len) != 0 ) Warning("Can't write UUID!");
           }
 
         break;
@@ -2531,11 +2579,13 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
     case ZAXIS_GENERIC:
       {
 	if ( editionNumber <= 1 )
-          gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", ltype);
+          {
+            grib1DefLevel(gh, gcinit, ltype, lbounds, level, dlevel1, dlevel2);
+          }
         else
-          gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", ltype);
-
-	GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
+          {
+            grib2DefLevel(gh, gcinit, ltype, ltype, lbounds, level, dlevel1, dlevel2);
+          }
 
 	break;
       }
@@ -2556,7 +2606,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
 {
   size_t recsize = 0;
   void *dummy = NULL;
-  int lieee = FALSE;
+  bool lieee = false;
   /*  int ensID, ensCount, forecast_type; *//* Ensemble Data */
   int typeOfGeneratingProcess;
   int productDefinitionTemplate;
@@ -2604,10 +2654,10 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
 
   if ( ! gc->init ) gribapiDefParam((int)editionNumber, gh, param, name, stdname);
 
-  if ( editionNumber == 2 && (datatype == DATATYPE_FLT32 || datatype == DATATYPE_FLT64) ) lieee = TRUE;
+  if ( editionNumber == 2 && (datatype == DATATYPE_FLT32 || datatype == DATATYPE_FLT64) ) lieee = true;
 
   /* bitsPerValue have to be defined before call to DefGrid (complex packing) */
-  //  if ( lieee == FALSE )
+  //  if ( lieee == false )
     {
       bitsPerValue = grbBitsPerValue(datatype);
       GRIB_CHECK(my_grib_set_long(gh, "bitsPerValue", bitsPerValue), 0);
diff --git a/libcdi/src/subtype.h b/libcdi/src/subtype.h
index db938c3..81135aa 100644
--- a/libcdi/src/subtype.h
+++ b/libcdi/src/subtype.h
@@ -49,13 +49,13 @@ typedef struct  {
   int                     subtype;               /* subtype kind: TILES, ... */
   int                     nentries;              /* counter: total no. of entries in list */
 
+  /* currently active subtype, e.g. GRIB2 tile index (for example for
+     stream/vlist accesses): */
+  int                     active_subtype_index;
   struct subtype_entry_t  globals;               /* global attributes */
 
   /* list of subtype entries, e.g. the list of tiles, ordered by entry->self. */
   struct subtype_entry_t *entries;
-  /* currently active subtype, e.g. GRIB2 tile index (for example for
-     stream/vlist accesses): */
-  int                     active_subtype_index;
 } subtype_t;
 
 
diff --git a/libcdi/src/timebase.c b/libcdi/src/timebase.c
index 0849fda..5371ea9 100644
--- a/libcdi/src/timebase.c
+++ b/libcdi/src/timebase.c
@@ -13,21 +13,16 @@ void decode_julday(int calendar,
 		   int *day)	/* Gregorian day (1-31) (out)   */
 {
   int a = julday;
-  double b, c;
-  double d, e, f;
 
-  b = floor((a - 1867216.25)/36524.25);
-  c = a + b - floor(b/4) + 1525;
+  double b = floor((a - 1867216.25)/36524.25);
+  double c = a + b - floor(b/4) + 1525;
 
   if ( calendar == CALENDAR_STANDARD )
-    if ( a < 2299161 )
-      {
-	c = a + 1524;
-      } 
+    if ( a < 2299161 ) c = a + 1524;
 
-  d = floor((c - 122.1)/365.25);
-  e = floor(365.25*d);
-  f = floor((c - e)/30.6001);
+  double d = floor((c - 122.1)/365.25);
+  double e = floor(365.25*d);
+  double f = floor((c - e)/30.6001);
 
   *day  = (int)(c - e - floor(30.6001*f));
   *mon  = (int)(f - 1 - 12*floor(f/14));
@@ -41,7 +36,6 @@ int encode_julday(int calendar, int year, int month, int day)
   int iy;
   int im;
   int ib;
-  int julday;
 
   if ( month <= 2 )
     {
@@ -77,63 +71,54 @@ int encode_julday(int calendar, int year, int month, int day)
 	}
     }
 
-  julday = (int) (floor(365.25*iy) + (int)(30.6001*(im+1)) + ib + 1720996.5 + day + 0.5);
+  int julday = (int) (floor(365.25*iy) + (int)(30.6001*(im+1)) + ib + 1720996.5 + day + 0.5);
 
-  return (julday);
+  return julday;
 }
 
 
 int date_to_julday(int calendar, int date)
 {
-  int julday;
   int year, month, day;
-
   cdiDecodeDate(date, &year, &month, &day);
 
-  julday = encode_julday(calendar, year, month, day);
+  int julday = encode_julday(calendar, year, month, day);
 
-  return (julday);
+  return julday;
 }
 
 
 int julday_to_date(int calendar, int julday)
 {
-  int date;
   int year, month, day;
-
   decode_julday(calendar, julday, &year, &month, &day);
 
-  date = cdiEncodeDate(year, month, day);
+  int date = cdiEncodeDate(year, month, day);
 
-  return (date);
+  return date;
 }
 
 
 int time_to_sec(int time)
 {
-  int secofday;
   int hour, minute, second;
-
   cdiDecodeTime(time, &hour, &minute, &second);
 
-  secofday = hour*3600 + minute*60 + second;
+  int secofday = hour*3600 + minute*60 + second;
 
-  return (secofday);
+  return secofday;
 }
 
 
 int sec_to_time(int secofday)
 {
-  int time;
-  int hour, minute, second;
+  int hour   = secofday/3600;
+  int minute = secofday/60 - hour*60;
+  int second = secofday - hour*3600 - minute*60;
 
-  hour   = secofday/3600;
-  minute = secofday/60 - hour*60;
-  second = secofday - hour*3600 - minute*60;
+  int time = cdiEncodeTime(hour, minute, second);
 
-  time = cdiEncodeTime(hour, minute, second);
-
-  return (time);
+  return time;
 }
 
 static
@@ -141,14 +126,14 @@ void adjust_seconds(int *julday, int64_t *secofday)
 {
   int64_t secperday = 86400;
 
-  while ( *secofday >= secperday ) 
-    { 
-      *secofday -= secperday; 
+  while ( *secofday >= secperday )
+    {
+      *secofday -= secperday;
       (*julday)++;
     }
 
-  while ( *secofday <  0 ) 
-    { 
+  while ( *secofday <  0 )
+    {
       *secofday += secperday;
       (*julday)--;
     }
@@ -182,19 +167,16 @@ void julday_add(int days, int secs, int *julday, int *secofday)
 /* subtract julday1/secofday1 from julday2/secofday2 and returns the result in seconds */
 double julday_sub(int julday1, int secofday1, int julday2, int secofday2, int *days, int *secs)
 {
-  int64_t sec_of_day;
-  int64_t seconds;
-
   *days = julday2 - julday1;
   *secs = secofday2 - secofday1;
 
-  sec_of_day = *secs;
+  int64_t sec_of_day = *secs;
 
   adjust_seconds(days, &sec_of_day);
 
   *secs = (int) sec_of_day;
 
-  seconds = *days * 86400 + sec_of_day;
+  int64_t seconds = (int64_t)(*days) * (int64_t)86400 + sec_of_day;
 
   return (double)seconds;
 }
diff --git a/libcdi/src/util.c b/libcdi/src/util.c
index cd8a6d2..cef54cf 100644
--- a/libcdi/src/util.c
+++ b/libcdi/src/util.c
@@ -8,6 +8,7 @@
 #include <float.h>
 #include <inttypes.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 
@@ -197,6 +198,7 @@ void cdiCreateUUID(unsigned char *uuid)
 {
   static int uuid_seeded = 0;
   static char uuid_rand_state[31 * sizeof (long)];
+#ifndef _SX
   char *caller_rand_state;
   if (uuid_seeded)
     caller_rand_state = setstate(uuid_rand_state);
@@ -216,11 +218,17 @@ void cdiCreateUUID(unsigned char *uuid)
     }
   for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
     uuid[i] = (unsigned char)random();
+#else
+  for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
+    uuid[i] = (unsigned char)lrand48();
+#endif
   /* encode variant into msb of octet 8 */
   uuid[8] = (unsigned char)((uuid[8] & 0x3f) | (1 << 7));
   /* encode version 4 ((pseudo-)random uuid) into msb of octet 7 */
   uuid[7] = (unsigned char)((uuid[7] & 0x0f) | (4 << 4));
+#ifndef _SX
   setstate(caller_rand_state);
+#endif
 }
 #endif
 
diff --git a/libcdi/src/vlist_var.c b/libcdi/src/vlist_var.c
index 3ad263e..12b63f0 100644
--- a/libcdi/src/vlist_var.c
+++ b/libcdi/src/vlist_var.c
@@ -17,7 +17,6 @@
 
 #if  defined  (HAVE_LIBGRIB_API)
 #  include "file.h"
-
 #  include <grib_api.h>
 #endif
 
@@ -172,7 +171,8 @@ int vlistDefVarTiles(int vlistID, int gridID, int zaxisID, int tsteptype, int ti
     @Item  gridID    Grid ID, from a previous call to @fref{gridCreate}.
     @Item  zaxisID   Z-axis ID, from a previous call to @fref{zaxisCreate}.
     @Item  tsteptype One of the set of predefined CDI timestep types.
-                     The valid CDI timestep types are @func{TSTEP_CONSTANT} and @func{TSTEP_INSTANT}.
+                     The valid CDI timestep types are @func{TSTEP_CONSTANT}, @func{TSTEP_INSTANT},
+                     @func{TSTEP_ACCUM}, @func{TSTEP_AVG}, @func{TSTEP_MAX}, @func{TSTEP_MIN} and @func{TSTEP_SD}.
 
 @Description
 The function @func{vlistDefVar} adds a new variable to vlistID.
@@ -304,10 +304,10 @@ void vlistInqVar(int vlistID, int varID, int *gridID, int *zaxisID, int *tstepty
     @Item  varID    Variable identifier.
 
 @Description
-The function @func{vlistInqVarGrid} returns the grid ID of a variable.
+The function @func{vlistInqVarGrid} returns the grid ID of a Variable.
 
 @Result
- at func{vlistInqVarGrid} returns the grid ID of the variable.
+ at func{vlistInqVarGrid} returns the grid ID of the Variable.
 
 @EndFunction
 */
@@ -1231,7 +1231,26 @@ void vlistDefVarTsteptype(int vlistID, int varID, int tsteptype)
     }
 }
 
+/*
+ at Function  vlistInqVarTsteptype
+ at Title     Get the timestep type of a Variable
+
+ at Prototype int vlistInqVarTsteptype(int vlistID, int varID)
+ at Parameter
+    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
+    @Item  varID    Variable identifier.
+
+ at Description
+The function @func{vlistInqVarTsteptype} returns the timestep type of a Variable.
+
+ at Result
+ at func{vlistInqVarTsteptype} returns the timestep type of the Variable,
+one of the set of predefined CDI timestep types.
+The valid CDI timestep types are @func{TSTEP_CONSTANT}, @func{TSTEP_INSTANT},
+ at func{TSTEP_ACCUM}, @func{TSTEP_AVG}, @func{TSTEP_MAX}, @func{TSTEP_MIN} and @func{TSTEP_SD}.
 
+ at EndFunction
+*/
 int vlistInqVarTsteptype(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
diff --git a/libcdi/src/zaxis.c b/libcdi/src/zaxis.c
index 10bdeaa..054b46c 100644
--- a/libcdi/src/zaxis.c
+++ b/libcdi/src/zaxis.c
@@ -65,7 +65,8 @@ enum {
 
 
 typedef struct {
-  unsigned char positive;
+  char     dimname[CDI_MAX_NAME];
+  char     vdimname[CDI_MAX_NAME];
   char     name[CDI_MAX_NAME];
   char     longname[CDI_MAX_NAME];
   char     stdname[CDI_MAX_NAME];
@@ -84,6 +85,7 @@ typedef struct {
   int      size;
   int      direction;
   int      vctsize;
+  unsigned positive;
   double  *vct;
   int      number;   /* Reference number to a generalized Z-axis */
   int      nhlev;
@@ -141,6 +143,8 @@ void zaxisDefaultValue(zaxis_t *zaxisptr)
   zaxisptr->name[0]     = 0;
   zaxisptr->longname[0] = 0;
   zaxisptr->stdname[0]  = 0;
+  zaxisptr->dimname[0]  = 0;
+  zaxisptr->vdimname[0] = 0;
   zaxisptr->units[0]    = 0;
   zaxisptr->psname[0]   = 0;
   zaxisptr->vals        = NULL;
@@ -354,6 +358,113 @@ void zaxisName(int zaxistype, char *zaxisname)
   strcpy(zaxisname, zaxisNamePtr(zaxistype));
 }
 
+static inline
+void zaxisSetString(char *zaxisstrname, const char *name, size_t len)
+{
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(zaxisstrname, name, len);
+  zaxisstrname[len - 1] = 0;
+}
+
+static inline
+void zaxisGetString(char *name, const char *zaxisstrname, size_t len)
+{
+  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
+  strncpy(name, zaxisstrname, len);
+  name[len - 1] = 0;
+}
+
+static
+char *zaxis_key_to_string(zaxis_t *zaxisptr, int key)
+{
+  char *zaxisstring = NULL;
+
+  switch (key)
+    {
+    case CDI_ZAXIS_DIMNAME:  zaxisstring = zaxisptr->dimname; break;
+    case CDI_ZAXIS_VDIMNAME: zaxisstring = zaxisptr->vdimname; break;
+    }
+
+  return zaxisstring;
+}
+
+/*
+ at Function  cdiZaxisDefString
+ at Title     Define a CDI Z-axis string value from a key
+
+ at Prototype int cdiZaxisDefString(int zaxisID, int key, int size, const char *mesg)
+ at Parameter
+    @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
+    @Item  key      The key to be searched
+    @Item  size     The allocated length of the string on input
+    @Item  mesg     The address of a string where the data will be read
+
+ at Description
+The function @func{cdiZaxisDefString} defines a CDI Z-axis string value from a key.
+
+ at Result
+ at func{cdiZaxisDefString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiZaxisDefString(int zaxisID, int key, int size, const char *mesg)
+{
+  if ( size <= 0 || mesg == NULL || *mesg == 0 ) return -1;
+
+  zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
+
+  char *zaxisstring = zaxis_key_to_string(zaxisptr, key);
+  if ( zaxisstring == NULL)
+    {
+      Warning("CDI zaxis string key %d not supported!", key);
+      return -1;
+    }
+
+  zaxisSetString(zaxisstring, mesg, (size_t)size);
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+
+  return 0;
+}
+
+/*
+ at Function  cdiZaxisInqString
+ at Title     Get a CDI Z-axis string value from a key
+
+ at Prototype int cdiZaxisInqString(int zaxisID, int key, int size, char *mesg)
+ at Parameter
+    @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
+    @Item  key      The key to be searched.
+    @Item  size     The allocated length of the string on input.
+    @Item  mesg     The address of a string where the data will be retrieved.
+                    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}.
+
+ at Description
+The function @func{cdiZaxisInqString} return a CDI Z-axis string value from a key.
+
+ at Result
+ at func{cdiZaxisInqString} returns 0 if OK and integer value on error.
+
+ at EndFunction
+*/
+int cdiZaxisInqString(int zaxisID, int key, int size, char *mesg)
+{
+  if ( size <= 0 || mesg == NULL ) return -1;
+
+  zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
+  const char *zaxisstring = zaxis_key_to_string(zaxisptr, key);
+  if ( zaxisstring == NULL)
+    {
+      Warning("CDI zaxis string key %d not supported!", key);
+      return -1;
+    }
+
+  zaxisGetString(mesg, zaxisstring, (size_t)size);
+
+  return 0;
+}
+
 /*
 @Function  zaxisDefName
 @Title     Define the name of a Z-axis
@@ -470,6 +581,12 @@ void zaxisInqName(int zaxisID, char *name)
   strcpy(name, zaxisptr->name);
 }
 
+const char *zaxisInqNamePtr(int zaxisID)
+{
+  zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
+  return zaxisptr->name;
+}
+
 /*
 @Function  zaxisInqLongname
 @Title     Get the longname of a Z-axis
@@ -558,9 +675,9 @@ void zaxisDefPositive(int zaxisID, int positive)
 {
   zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
 
-  if (zaxisptr->positive != positive)
+  if (zaxisptr->positive != (unsigned)(positive != 0))
     {
-      zaxisptr->positive = (unsigned char)positive;
+      zaxisptr->positive = (unsigned)(positive != 0);
       reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -569,7 +686,7 @@ void zaxisDefPositive(int zaxisID, int positive)
 int zaxisInqPositive(int zaxisID)
 {
   zaxis_t *zaxisptr = zaxisID2Ptr(zaxisID);
-  return zaxisptr->positive;
+  return (int)zaxisptr->positive;
 }
 
 
@@ -1202,6 +1319,9 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
 
   int type    = zaxisptr->type;
   int nlevels = zaxisptr->size;
+  int prec    = zaxisptr->prec;
+
+  int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
 
   int nbyte0 = 0;
   fprintf(fp, "#\n");
@@ -1223,7 +1343,7 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
 	  fprintf(fp, "%*s", nbyte0, "");
 	  nbyte = nbyte0;
 	}
-      nbyte += fprintf(fp, "%.9g ", zaxisptr->vals[levelID]);
+      nbyte += fprintf(fp, "%.*g ", dig, zaxisptr->vals[levelID]);
     }
   fprintf(fp, "\n");
 
@@ -1239,7 +1359,7 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
 	      fprintf(fp, "%*s", nbyte0, "");
 	      nbyte = nbyte0;
 	    }
-	  nbyte += fprintf(fp, "%.9g ", zaxisptr->lbounds[levelID]);
+	  nbyte += fprintf(fp, "%.*g ", dig, zaxisptr->lbounds[levelID]);
 	}
       fprintf(fp, "\n");
 
@@ -1253,7 +1373,7 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
 	      fprintf(fp, "%*s", nbyte0, "");
 	      nbyte = nbyte0;
 	    }
-	  nbyte += fprintf(fp, "%.9g ", zaxisptr->ubounds[levelID]);
+	  nbyte += fprintf(fp, "%.*g ", dig, zaxisptr->ubounds[levelID]);
 	}
       fprintf(fp, "\n");
     }
@@ -1274,7 +1394,7 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
                   fprintf(fp, "\n%*s", nbyte0, "");
                   nbyte = nbyte0;
                 }
-              nbyte += fprintf(fp, "%.9g ", vct[i]);
+              nbyte += fprintf(fp, "%.15g ", vct[i]);
             }
           fprintf(fp, "\n");
           /*
@@ -1287,7 +1407,7 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
                   fprintf(fp, "\n%*s", nbyte0, "");
                   nbyte = nbyte0;
                 }
-              nbyte += fprintf(fp, "%.9g ", vct[vctsize/2+i]);
+              nbyte += fprintf(fp, "%.15g ", vct[vctsize/2+i]);
             }
           fprintf(fp, "\n");
           */
diff --git a/libcdi/src/zaxis.h b/libcdi/src/zaxis.h
index 95c35e3..2c5bceb 100644
--- a/libcdi/src/zaxis.h
+++ b/libcdi/src/zaxis.h
@@ -16,6 +16,8 @@ void zaxisDefLtype2(int zaxisID, int ltype2);
 
 const resOps *getZaxisOps(void);
 
+const char *zaxisInqNamePtr(int zaxisID);
+
 #endif
 
 /*
diff --git a/libcdi/tests/Makefile.am b/libcdi/tests/Makefile.am
index c5efabd..5dd60ce 100644
--- a/libcdi/tests/Makefile.am
+++ b/libcdi/tests/Makefile.am
@@ -66,3 +66,8 @@ EXTRA_DIST = test_cdf_write.c test_cdf_read.c
 CLEANFILES  = `ls *~ *.grb *.nc *.srv *.ext example_*.cksum`
 #
 AUTOMAKE_OPTIONS = color-tests
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
diff --git a/libcdi/tests/Makefile.in b/libcdi/tests/Makefile.in
index 7a86bff..632acad 100644
--- a/libcdi/tests/Makefile.in
+++ b/libcdi/tests/Makefile.in
@@ -361,6 +361,7 @@ ENABLE_IEG = @ENABLE_IEG@
 ENABLE_MPI = @ENABLE_MPI@
 ENABLE_NC2 = @ENABLE_NC2@
 ENABLE_NC4 = @ENABLE_NC4@
+ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
 ENABLE_NETCDF = @ENABLE_NETCDF@
 ENABLE_PYTHON = @ENABLE_PYTHON@
 ENABLE_RUBY = @ENABLE_RUBY@
@@ -383,9 +384,6 @@ GREP = @GREP@
 GRIB_API_INCLUDE = @GRIB_API_INCLUDE@
 GRIB_API_LIBS = @GRIB_API_LIBS@
 HAVE_PARALLEL_NC4 = @HAVE_PARALLEL_NC4@
-HDF5_INCLUDE = @HDF5_INCLUDE@
-HDF5_LIBS = @HDF5_LIBS@
-HDF5_ROOT = @HDF5_ROOT@
 HOST_NAME = @HOST_NAME@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -458,8 +456,6 @@ UUID_C_LIB = @UUID_C_LIB@
 VERSION = @VERSION@
 YAXT_CFLAGS = @YAXT_CFLAGS@
 YAXT_LIBS = @YAXT_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -978,7 +974,7 @@ maintainer-clean-generic:
 	@echo "it deletes files that may require special tools to rebuild."
 clean: clean-am
 
-clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \
 	mostlyclean-am
 
 distclean: distclean-am
@@ -1050,19 +1046,24 @@ uninstall-am:
 .MAKE: check-am install-am install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
-	clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \
-	ctags ctags-am distclean distclean-compile distclean-generic \
-	distclean-libtool distclean-tags distdir dvi dvi-am html \
-	html-am info info-am install install-am install-data \
-	install-data-am install-dvi install-dvi-am install-exec \
-	install-exec-am install-html install-html-am install-info \
-	install-info-am install-man install-pdf install-pdf-am \
-	install-ps install-ps-am install-strip installcheck \
-	installcheck-am installdirs maintainer-clean \
+	clean-checkPROGRAMS clean-generic clean-libtool clean-local \
+	cscopelist-am ctags ctags-am distclean distclean-compile \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
 	maintainer-clean-generic mostlyclean mostlyclean-compile \
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
 	tags tags-am uninstall uninstall-am
 
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
 
 # 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/m4/acx_options.m4 b/m4/acx_options.m4
index 94a5232..c1058ab 100644
--- a/m4/acx_options.m4
+++ b/m4/acx_options.m4
@@ -31,36 +31,11 @@ AC_SUBST([ENABLE_THREADS])
 AC_SUBST([THREADS_INCLUDE])
 AC_SUBST([THREADS_LIBS])
 #  ----------------------------------------------------------------------
-#  Link application to ZLIB library, needed for netcdf
-ZLIB_INCLUDE=''
-ZLIB_LIBS=''
-AC_ARG_WITH([zlib],
-            [AS_HELP_STRING([--with-zlib=<yes|no|directory> (default=yes)],[location of ZLIB compression library (lib and include subdirs), nec. for HDF5/NETCDF4])],
-            [AS_CASE(["$with_zlib"],
-                     [no],[AC_MSG_CHECKING([for ZLIB library])
-                           AC_MSG_RESULT([suppressed])],
-                     [yes],[AC_CHECK_HEADERS(zlib.h)
-                            AC_SEARCH_LIBS([deflate],[z],[AC_DEFINE([HAVE_LIBZ],[1],[Define 1 for ZLIB support])])
-                            ZLIB_LIBS=" -lz"],
-                     [*],[ZLIB_ROOT=$with_zlib
-                          LDFLAGS="-L$ZLIB_ROOT/lib $LDFLAGS"
-                          CPPFLAGS="-I$ZLIB_ROOT/include $CPPFLAGS"
-                          AC_CHECK_HEADERS(zlib.h)
-                          AC_SEARCH_LIBS([deflate],[z],[AC_DEFINE([HAVE_LIBZ],[1],[Define 1 for ZLIB support])])
-                          ZLIB_INCLUDE=" -I$ZLIB_ROOT/include"
-                          ZLIB_LIBS=" -L$ZLIB_ROOT/lib -lz"])],
-                     [AC_CHECK_HEADERS(zlib.h)
-                      AC_SEARCH_LIBS([deflate],[z],[AC_DEFINE([HAVE_LIBZ],[1],[Define 1 for ZLIB support])])
-              ZLIB_LIBS=" -lz"])
-AC_SUBST([ZLIB_INCLUDE])
-AC_SUBST([ZLIB_LIBS])
-#  ----------------------------------------------------------------------
-#  Compile application with SZLIB library, needed for GRIB1 or for
-#  linking against hdf5/netcdf4
+#  Compile application with SZLIB library, needed for GRIB1 linking
 SZLIB_INCLUDE=''
 SZLIB_LIBS=''
 AC_ARG_WITH([szlib],
-            [AS_HELP_STRING([--with-szlib=<yes|no|directory> (default=no)],[location of szlib library, optional for GRIB1 and NETCDF4 compression])],
+            [AS_HELP_STRING([--with-szlib=<yes|no|directory> (default=no)],[location of szlib library, optional for GRIB1 compression])],
             [AS_CASE(["$with_szlib"],
                      [no],[AC_MSG_CHECKING([for szlib library])
                            AC_MSG_RESULT([suppressed])],
@@ -92,7 +67,7 @@ HDF5_ROOT=''
 HDF5_INCLUDE=''
 HDF5_LIBS=''
 AC_ARG_WITH([hdf5],
-            [AS_HELP_STRING([--with-hdf5=<yes|no|directory> (default=no)],[location of hdf5 library, NETCDF4 requires hdf5 high level interface])],
+            [AS_HELP_STRING([--with-hdf5=<yes|no|directory> (default=no)],[location of HDF5 library])],
             [AS_CASE(["$with_hdf5"],
                      [no],[AC_MSG_CHECKING([for hdf5 library])
                            AC_MSG_RESULT([suppressed])],
@@ -100,11 +75,11 @@ AC_ARG_WITH([hdf5],
                             AC_SEARCH_LIBS([H5Fopen],
                                            [hdf5],
                                            [AC_DEFINE([HAVE_LIBHDF5],[1],[Define to 1 for HDF5 support])],
-                                           [AC_MSG_ERROR([Cannot link to hdf5 library! It is required for Netcdf4])])
+                                           [AC_MSG_ERROR([Cannot link to hdf5 library!])])
                             AC_SEARCH_LIBS([H5DSis_scale],
                                            [hdf5_hl],
                                            [have_hdf5_hl=yes],
-                                           [AC_MSG_NOTICE([Cannot find hdf5 high level interface! It is required for netCDF4.])
+                                           [AC_MSG_NOTICE([Cannot find hdf5 high level interface!])
                                             have_hdf5_hl=no])
                             AS_IF([test "x$have_libhdf5_hl" = xyes],
                                   [HDF5_LIBS=" -lhdf5_hl -lhdf5"],
@@ -118,14 +93,11 @@ AC_ARG_WITH([hdf5],
                                  AC_SEARCH_LIBS([H5Fopen],
                                                 [hdf5],
                                                 [AC_DEFINE([HAVE_LIBHDF5],[1],[Define to 1 for HDF5 support])],
-                                                [AC_MSG_ERROR([Cannot link to hdf5! It is required for netCDF4.])])
+                                                [AC_MSG_ERROR([Cannot link to hdf5!])])
                                  AC_SEARCH_LIBS([H5DSis_scale],
                                                 [hdf5_hl],
                                                 [have_hdf5_hl=yes],
-                                                [AC_MSG_NOTICE([Cannot link to hdf5 high level interface! It is required for netCDF4.\
-                                                                HDF5 must be built with zlib; the location of zlib must be specified for HDF5 with the \
-                                                                --with-zlib option. If HDF5 was also built with szlib, then the location of szlib must also be \
-                                                                specified with the --with-szlib option..])
+                                                [AC_MSG_NOTICE([Cannot link to hdf5 high level interface!])
                                                 have_hdf5_hl=no])
                                  AS_IF([test "x$have_libhdf5_hl" = 'xyes'],
                                        [HDF5_LIBS=" -L$HDF5_ROOT/lib -lhdf5_hl -lhdf5"],
@@ -147,33 +119,32 @@ ENABLE_NC2=no
 ENABLE_NC4=no
 ENABLE_NC4HDF5=no
 AC_ARG_WITH([netcdf],
-            [AS_HELP_STRING([--with-netcdf=<yes|no|directory> (default=no)],[location of netCDF library (lib and include subdirs)])],
+            [AS_HELP_STRING([--with-netcdf=<yes|no|directory> (default=no)],[location of NetCDF library (lib and include subdirs)])],
             [AS_CASE(["$with_netcdf"],
-                     [no],[AC_MSG_CHECKING([for netCDF library])
+                     [no],[AC_MSG_CHECKING([for NetCDF library])
                            AC_MSG_RESULT([suppressed])],
                      [yes],[AC_CHECK_HEADERS([netcdf.h])
                             AC_SEARCH_LIBS([nc_open],
                                            [netcdf],
-                                           [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for netCDF support])
+                                           [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for NetCDF support])
                                             ENABLE_NETCDF=yes],
-                                           [AC_MSG_ERROR([Could not link to netCDF library])])
+                                           [AC_MSG_ERROR([Could not link to NetCDF library])])
                             NETCDF_LIBS=" -lnetcdf"
-			    
                             AC_CHECK_PROG(NC_CONFIG,nc-config,nc-config)
                             AS_IF([test "x$NC_CONFIG" != "x"],
                                   [AC_MSG_CHECKING([netcdf's nc2 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc2)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for netCDF2 support])
+                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for NetCDF2 support])
                                           ENABLE_NC2=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
                                    AC_MSG_CHECKING([netcdf's nc4 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc4)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NETCDF4 support])
+                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NetCDF4 support])
                                           ENABLE_NC4=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
 			           AC_MSG_CHECKING([netcdf's nc4/hdf5 support])
                                    AS_IF([test "x$($NC_CONFIG --has-hdf5)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NC4HDF5],[1],[Define to 1 for NETCDF4/HDF5 support])
+                                         [AC_DEFINE([HAVE_NC4HDF5],[1],[Define to 1 for NetCDF4/HDF5 support])
                                           ENABLE_NC4HDF5=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])]) ],
                                   [AS_ECHO([Could not find nc-config! go on with default configuration])])],
@@ -184,42 +155,41 @@ AC_ARG_WITH([netcdf],
                                  AC_CHECK_HEADERS([netcdf.h])
                                  AC_SEARCH_LIBS([nc_open],
                                                 [netcdf],
-                                                [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for NETCDF support])
+                                                [AC_DEFINE([HAVE_LIBNETCDF],[1],[Define to 1 for NetCDF support])
                                                  ENABLE_NETCDF=yes],
-                                                [AC_MSG_ERROR([Could not link to netcdf library])])
+                                                [AC_MSG_ERROR([Could not link to NetCDF library])])
                                  NETCDF_LIBS=" -L$NETCDF_ROOT/lib -lnetcdf"
                                  NETCDF_INCLUDE=" -I$NETCDF_ROOT/include"
-
                                  AC_MSG_CHECKING([nc-config script])
                                  AC_CHECK_PROG(NC_CONFIG,nc-config,[$NETCDF_ROOT/bin/nc-config],,["$NETCDF_ROOT/bin"])
                                  AS_IF([test "x$NC_CONFIG" != "x"],
                                    [AC_MSG_CHECKING([netcdf's OpenDAP support])
                                    AS_IF([test "x$($NC_CONFIG --has-dap)" = "xyes"],
-                                         [AC_DEFINE([HAVE_LIBNC_DAP],[1],[Define to 1 for NETCDF OpenDAP])
+                                         [AC_DEFINE([HAVE_LIBNC_DAP],[1],[Define to 1 for NetCDF OpenDAP])
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])]
                                    [AC_MSG_CHECKING([netcdf's nc2 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc2)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for NETCDF2 support])
+                                         [AC_DEFINE([HAVE_NETCDF2],[1],[Define to 1 for NetCDF2 support])
                                           ENABLE_NC2=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
                                    AC_MSG_CHECKING([netcdf's nc4 support])
                                    AS_IF([test "x$($NC_CONFIG --has-nc4)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NETCDF4 support])
+                                         [AC_DEFINE([HAVE_NETCDF4],[1],[Define to 1 for NetCDF4 support])
                                           ENABLE_NC4=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])])
 			           AC_MSG_CHECKING([netcdf's nc4/hdf5 support])
                                    AS_IF([test "x$($NC_CONFIG --has-hdf5)" = "xyes"],
-                                         [AC_DEFINE([HAVE_NC4HDF5],[1],[Define to 1 for NETCDF4/HDF5 support])
+                                         [AC_DEFINE([HAVE_NC4HDF5],[1],[Define to 1 for NetCDF4/HDF5 support])
                                           ENABLE_NC4HDF5=yes
                                           AC_MSG_RESULT([yes])],[AC_MSG_RESULT([no])]) ],
                                    [AC_MSG_RESULT([Could not find nc-config! go on with default configuration])])],
-                                [AC_MSG_NOTICE([$with_netcdf is not a directory! NETCDF suppressed])])])],
-            [AC_MSG_CHECKING([for NETCDF library])
+                                [AC_MSG_NOTICE([$with_netcdf is not a directory! NetCDF suppressed])])])],
+            [AC_MSG_CHECKING([for NetCDF library])
              AC_MSG_RESULT([suppressed])])
 
 AS_IF([test "x$ENABLE_NC4HDF5" = "xyes"],
       [AC_SEARCH_LIBS([H5TS_mutex_lock], [netcdf],
-               [AC_DEFINE([HAVE_NC4HDF5_THREADSAFE],[1],[Define to 1 for NETCDF4/HDF5 threadsafe support])],,
+               [AC_DEFINE([HAVE_NC4HDF5_THREADSAFE],[1],[Define to 1 for NetCDF4/HDF5 threadsafe support])],,
 	       [-lhdf5_hl -lhdf5])])
 
 AC_SUBST([ENABLE_NETCDF])
@@ -230,11 +200,40 @@ AC_SUBST([NETCDF_ROOT])
 AC_SUBST([NETCDF_INCLUDE])
 AC_SUBST([NETCDF_LIBS])
 #  ----------------------------------------------------------------------
+#  Link application with UDUNITS2 library
+AC_ARG_WITH([udunits2],
+            [AS_HELP_STRING([--with-udunits2=<directory>],
+                            [Specify location of UDUNITS2 library.])],
+            [AS_CASE(["$with_udunits2"],
+                     [no],[AC_MSG_CHECKING([for udunits2 library])
+                           AC_MSG_RESULT([suppressed])],
+                     [yes],[AC_CHECK_HEADERS([udunits2.h])
+                            AC_SEARCH_LIBS([ut_parse],
+                                           [udunits2],
+                                           [AC_DEFINE([HAVE_LIBUDUNITS2],[1],[Define to 1 for UDUNITS2 support])],
+                                           [AC_MSG_ERROR([Could not link to udunits2 library!])])
+                            AC_SUBST([UDUNITS_LDFLAGS],[" -ludunits2"])
+                            AC_SUBST([UDUNITS_INCLUDE],[""])],
+                     [*],[UDUNITS_ROOT=$with_udunits2
+                          AS_IF([test -d "$UDUNITS_ROOT"],
+                                [LDFLAGS="$LDFLAGS -L$UDUNITS_ROOT/lib"
+                                 CPPFLAGS="$CPPFLAGS -I$UDUNITS_ROOT/include -I$UDUNITS_ROOT/include/udunits2"
+                                 AC_CHECK_HEADERS([udunits2.h])
+                                 AC_CHECK_HEADERS([udunits2/udunits2.h])
+                                 AC_SEARCH_LIBS([ut_parse],
+                                                [udunits2],
+                                                [AC_DEFINE([HAVE_LIBUDUNITS2],[1],[Define to 1 for UDUNITS2 support])],
+                                                [AC_MSG_ERROR([Could not link to udunits2 library!])])
+                                 AC_SUBST([UDUNITS_LDFLAGS],[" -L$UDUNITS_ROOT/lib -ludunits2"])
+                                 AC_SUBST([UDUNITS_INCLUDE],[" -I$UDUNITS_ROOT/include"])],
+                                [AC_MSG_ERROR([$UDUNITS_ROOT is not a directory! UDUNITS2 suppressed])])])],
+            [AC_MSG_CHECKING([for the UDUNITS2 library])
+             AC_MSG_RESULT([suppressed])])
+#  ----------------------------------------------------------------------
 #  Link application with CMOR library
 CMOR_LIBS=''
 AC_ARG_WITH([cmor],
-            [AS_HELP_STRING([--with-cmor=<directory>],
-                            [Specify location of CMOR library.])],
+            [AS_HELP_STRING([--with-cmor=<directory>],[Specify location of CMOR library.])],
             [AS_CASE(["$with_cmor"],
                      [no],[AC_MSG_CHECKING([for cmor library])
                            AC_MSG_RESULT([suppressed])],
@@ -245,7 +244,7 @@ AC_ARG_WITH([cmor],
                      [*],[CMOR_ROOT=$with_cmor
                           AS_IF([test -d "$CMOR_ROOT"],
                                 [LDFLAGS="$LDFLAGS -L$CMOR_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$CMOR_ROOT/include"
+                                 CPPFLAGS="$CPPFLAGS -I$CMOR_ROOT/include -I$CMOR_ROOT/include/cdTime"
                                  AC_SEARCH_LIBS([cmor_load_table],
                                                 [cmor],
                                                 [AC_DEFINE([HAVE_LIBCMOR],[1],[Define to 1 for CMOR support])],
@@ -419,36 +418,6 @@ AC_ARG_WITH([curl],
             [AC_MSG_CHECKING([for the CURL library])
              AC_MSG_RESULT([suppressed])])
 #  ----------------------------------------------------------------------
-#  Link application with UDUNITS2 library
-AC_ARG_WITH([udunits2],
-            [AS_HELP_STRING([--with-udunits2=<directory>],
-                            [Specify location of UDUNITS2 library.])],
-            [AS_CASE(["$with_udunits2"],
-                     [no],[AC_MSG_CHECKING([for udunits2 library])
-                           AC_MSG_RESULT([suppressed])],
-                     [yes],[AC_CHECK_HEADERS([udunits2.h])
-                            AC_SEARCH_LIBS([ut_parse],
-                                           [udunits2],
-                                           [AC_DEFINE([HAVE_LIBUDUNITS2],[1],[Define to 1 for UDUNITS2 support])],
-                                           [AC_MSG_ERROR([Could not link to udunits2 library!])])
-                            AC_SUBST([UDUNITS_LDFLAGS],[" -ludunits2"])
-                            AC_SUBST([UDUNITS_INCLUDE],[""])],
-                     [*],[UDUNITS_ROOT=$with_udunits2
-                          AS_IF([test -d "$UDUNITS_ROOT"],
-                                [LDFLAGS="$LDFLAGS -L$UDUNITS_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$UDUNITS_ROOT/include"
-                                 AC_CHECK_HEADERS([udunits2.h])
-                                 AC_CHECK_HEADERS([udunits2/udunits2.h])
-                                 AC_SEARCH_LIBS([ut_parse],
-                                                [udunits2],
-                                                [AC_DEFINE([HAVE_LIBUDUNITS2],[1],[Define to 1 for UDUNITS2 support])],
-                                                [AC_MSG_ERROR([Could not link to udunits2 library!])])
-                                 AC_SUBST([UDUNITS_LDFLAGS],[" -L$UDUNITS_ROOT/lib -ludunits2"])
-                                 AC_SUBST([UDUNITS_INCLUDE],[" -I$UDUNITS_ROOT/include"])],
-                                [AC_MSG_ERROR([$UDUNITS_ROOT is not a directory! UDUNITS2 suppressed])])])],
-            [AC_MSG_CHECKING([for the UDUNITS2 library])
-             AC_MSG_RESULT([suppressed])])
-#  ----------------------------------------------------------------------
 #  Compile application with MAGICS (xml required)
 MAGICS_ROOT=''
 MAGICS_INCLUDE=''
diff --git a/src/Afterburner.c b/src/Afterburner.c
index c7a3f9f..056b19d 100644
--- a/src/Afterburner.c
+++ b/src/Afterburner.c
@@ -301,7 +301,7 @@ void after_setDateTime(struct Date *datetime, int date, int time)
 static
 void after_printProcessStatus(int tsID)
 {
-  static int counthead = FALSE;
+  static bool counthead = false;
 
   if ( tsID == -1 )
     {
@@ -311,16 +311,16 @@ void after_printProcessStatus(int tsID)
 	  fflush(stdout);
 	}
 
-      counthead = FALSE;
+      counthead = false;
     }
   else
     {
-      if ( counthead == FALSE )
+      if ( counthead == false )
 	{
 	  if ( stdout_is_tty )
 	    fprintf(stdout, " Process timestep :       ");
 
-	  counthead = TRUE;
+	  counthead = true;
 	}
 
       if ( stdout_is_tty )
@@ -338,7 +338,7 @@ int after_setNextDate(struct Control *globs)
   int i;
   int vdate, vtime;
 
-  int righttime = FALSE;
+  bool righttime = false;
   while ( TRUE )
     {
       nrecs = streamInqTimestep(globs->istreamID, TsID);
@@ -367,7 +367,7 @@ int after_setNextDate(struct Control *globs)
       for ( i = 0; i < nrqh; i++ )
 	if ( hours[i] < 0 || hours[i] == globs->NextDate.hr )
 	  {
-	    righttime = TRUE;
+	    righttime = true;
 	    break;
 	  }
 
@@ -377,7 +377,7 @@ int after_setNextDate(struct Control *globs)
 	TsID += 1;	  
     }
 
-  return (nrecs);
+  return nrecs;
 }
 
 
@@ -390,15 +390,12 @@ void *after_readTimestep(void *arg)
   int recID, varID, gridID, zaxisID, levelID, timeID;
   int code, leveltype;
   int nmiss;
-  int analysisData, nrecs;
-  struct Variable *vars;
-  struct Control *globs;
   RARG *rarg = (RARG *) arg;
 
-  nrecs        = rarg->nrecs;
-  analysisData = rarg->lana;
-  vars         = rarg->vars;
-  globs        = rarg->globs;
+  int nrecs        = rarg->nrecs;
+  int analysisData = rarg->lana;
+  struct Variable *vars = rarg->vars;
+  struct Control *globs = rarg->globs;
 
   for ( code = 0; code < MaxCodes; code++ ) vars[code].nmiss0 = 0;
 
@@ -470,7 +467,7 @@ void *after_readTimestep(void *arg)
   */
   num_recs = after_setNextDate(globs);
 
-  return ((void *) &num_recs);
+  return (void *) &num_recs;
 }
 
 static
@@ -486,6 +483,8 @@ void after_defineNextTimestep(struct Control *globs)
     {
       if ( otsID == 0 )
 	{
+          int nvars = vlistNvars(globs->ovlistID);
+          if ( nvars == 0 ) Error("No variable selected!");
 	  vlistDefTaxis(globs->ovlistID, globs->taxisID2);
 	  streamDefVlist(globs->ostreamID, globs->ovlistID);
 	}
@@ -560,6 +559,69 @@ void after_moveTimestep(struct Variable *vars)
 }
 
 static
+void after_check_content(struct Variable *vars, int timestep)
+{
+  extern int labort_after;
+  for ( int code = 0; code < 272; code++ )
+    {
+      /*  if ( code == GEOPOTENTIAL ) continue; */
+      if ( code ==          SLP ) continue;
+      if ( code == GEOPOTHEIGHT ) continue;
+      if ( code ==       STREAM ) continue;
+      if ( code ==      VELOPOT ) continue;
+      if ( code ==       U_WIND ) continue;
+      if ( code ==       V_WIND ) continue;
+      if ( code ==        OMEGA ) continue;
+      if ( code ==    RHUMIDITY ) continue;
+      if ( code ==    LOW_CLOUD ) continue;
+      if ( code ==    MID_CLOUD ) continue;
+      if ( code ==    HIH_CLOUD ) continue;
+      if ( code ==           PS ) continue;
+      if ( code ==     HUMIDITY )
+	{
+	  if ( vars[code].needed && !vars[code].selected &&
+	       vars[code].spectral == NULL &&
+	       vars[code].hybrid   == NULL )
+	    {
+              static bool lwarn = true;
+              if ( lwarn ) Warning( "No humidity in data file, set to zero !");
+              lwarn = false;
+	      vars[code].needed = FALSE;
+	    }
+	}
+      else
+	{
+	  if ( vars[code].needed && !vars[code].comp &&
+	       vars[code].spectral == NULL &&
+	       vars[code].hybrid   == NULL )
+	    {
+	      if ( labort_after )
+		Error( "Code  %3d not found at timestep %d!", code, timestep);
+	      else
+		Warning( "Code  %3d not found at timestep %d!", code, timestep);
+	    }
+	}
+    }
+  /*
+  if ( NumLevelRequest > 0 )
+    {
+      vars[HALF_PRESS].needed = 1;
+      vars[FULL_PRESS].needed = 1;
+    }
+
+  code = HALF_PRESS;
+  if ( vars[code].needed && !vars[code].comp &&
+       vars[code].spectral == NULL && vars[code].hybrid == NULL )
+    Error( "Hybrid model level not found!");
+
+  code = FULL_PRESS;
+  if ( vars[code].needed && !vars[code].comp &&
+       vars[code].spectral == NULL && vars[code].hybrid == NULL )
+    Error( "Hybrid model level not found!");
+  */
+}
+
+static
 void after_control(struct Control *globs, struct Variable *vars)
 {
   int i;
@@ -581,7 +643,7 @@ void after_control(struct Control *globs, struct Variable *vars)
       pthread_attr_init(&attr);
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
       int status = pthread_attr_getstacksize(&attr, &stacksize);
-      if ( stacksize < 2097152 )
+      if ( status && stacksize < 2097152 )
 	{
 	  stacksize = 2097152;
 	  pthread_attr_setstacksize(&attr, stacksize);
@@ -594,7 +656,7 @@ void after_control(struct Control *globs, struct Variable *vars)
 
   TsID = 0;
 
-  int righttime = FALSE;
+  bool righttime = false;
   while ( (nrecs = streamInqTimestep(globs->istreamID, TsID)) > 0 )
     {
       vdate = taxisInqVdate(globs->taxisID);
@@ -605,7 +667,7 @@ void after_control(struct Control *globs, struct Variable *vars)
       for ( i = 0; i < nrqh; i++ )
 	if ( hours[i] < 0 || hours[i] == globs->NewDate.hr )
 	  {
-	    righttime = TRUE;
+	    righttime = true;
 	    break;
 	  }
 
@@ -704,8 +766,12 @@ void after_control(struct Control *globs, struct Variable *vars)
 
       if ( lstdout && globs->EndOfInterval ) after_printProcessStatus(-1);
       
-      if ( globs->Mean == 0 || globs->EndOfInterval ) after_defineNextTimestep(globs);
-
+      if ( globs->Mean == 0 || globs->EndOfInterval )
+        {
+          if ( !globs->AnalysisData ) after_check_content(vars, globs->TermCount+1);
+          after_defineNextTimestep(globs);
+        }
+      
       if ( globs->AnalysisData )
 	after_processPL(globs, vars);
       else
@@ -738,7 +804,7 @@ void after_setLevel(struct Control *globs)
   int k, l, found;
   int removeLevel[MaxLevel];
   double level;
-  int checkLevel = TRUE;
+  bool checkLevel = true;
   int numplevelDefault;  /* default pressure level */
   long plevelDefault[] = { 100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000,
                             10000,  7000,  5000,  3000,  2000, 1000 };
@@ -795,20 +861,20 @@ void after_setLevel(struct Control *globs)
 	      oVertID = iVertID;
 	    }
 	}
-      checkLevel = FALSE;
+      checkLevel = false;
     }
   else
     {
       if ( iVertID == -1 )
 	{
 	  if ( globs->Verbose )	fprintf(stdout," No level detected\n");
-	  checkLevel = FALSE;
+	  checkLevel = false;
 	}
       else if ( globs->NumLevelRequest == 1 && IS_EQUAL(globs->LevelRequest[0], 0) )
 	{
 	  if ( globs->Verbose ) fprintf(stdout," No level selected\n");
 	  globs->NumLevelRequest = 0;
-	  checkLevel = FALSE;
+	  checkLevel = false;
 	}
       else if ( globs->Verbose )
 	{
@@ -982,11 +1048,14 @@ void after_defineLevel(struct Control *globs, struct Variable *vars)
 	  if ( vars[code].selected )
 	    {
 	      if ( vars[code].izaxisID != -1 )
-		if ( zaxisInqType(vars[code].izaxisID) == zaxisInqType(iVertID) &&
-		     zaxisInqSize(vars[code].izaxisID) == globs->NumLevel &&
-		     zaxisInqSize(vars[code].izaxisID) >  1 )
-		  vars[code].ozaxisID = oVertID;
-	    }
+                {
+                  int nlev = zaxisInqSize(vars[code].izaxisID);
+                  if ( zaxisInqType(vars[code].izaxisID) == zaxisInqType(iVertID) &&
+                       (nlev == globs->NumLevel || nlev == globs->NumLevel+1) &&
+                       nlev >  1 )
+                    vars[code].ozaxisID = oVertID;
+                }
+            }
 	}
 
       break;
@@ -1424,13 +1493,13 @@ void after_precntl(struct Control *globs, struct Variable *vars)
       else if ( gridtype == GRID_GAUSSIAN && globs->Latitudes == 0 )
 	{
 	  gaussGridID = gridID;
-	  globs->Longitudes  = gridInqXsize(gridID);
-	  globs->Latitudes   = gridInqYsize(gridID);
+	  globs->Longitudes = gridInqXsize(gridID);
+	  globs->Latitudes  = gridInqYsize(gridID);
 	}
     }
 
   if ( globs->Truncation == 0 && globs->Latitudes == 0 )
-    Error("Unsupported file structure!");
+    Error("Unsupported file structure (no spectral or Gaussian data found)!");
 
   if ( globs->Truncation == 0 )
     {
@@ -1483,6 +1552,8 @@ void after_precntl(struct Control *globs, struct Variable *vars)
                       continue;
 		    }
 		}
+              else if ( leveltype == ZAXIS_HYBRID && globs->nvct == zaxisInqVctSize(zaxisID) )
+                continue;
 
 	      if ( iVertID != - 1 )
 		Warning( "More than %d different vertical grid structure found!", vertfound);
@@ -1876,10 +1947,9 @@ static
 void after_printCodes(void)
 {
   int tableID = tableInq(-1, 128, "echam4");
-  int ncodes;
   int codes[] = {34,35,36,131,132,135,148,149,151,156,157,259,260,261,262,263,264,268,269,270,271,275};
 
-  ncodes = sizeof(codes)/sizeof(codes[0]);
+  int ncodes = sizeof(codes)/sizeof(codes[0]);
 
   lprintf(stdout);
 
@@ -1916,35 +1986,29 @@ void after_printCodes(void)
 static
 void after_procstat(char *procpath, int truncation)
 {
-  FILE *sf;
-  double MaxMBytes;
   time_t tp;
-  long  yy, mm, dd, hh, mi;
   char mtype[12];
-  char *proc;
-  char *name;
   char  stat_file[128];
-  double CPUTime;
 
-  CPUTime = ((double) clock() - starttime ) / CLOCKS_PER_SEC;
+  double CPUTime = ((double) clock() - starttime ) / CLOCKS_PER_SEC;
 
   (void) time(&tp);
-  yy    = gmtime(&tp)->tm_year + 1900;
-  mm    = gmtime(&tp)->tm_mon + 1;
-  dd    = gmtime(&tp)->tm_mday   ;
-  hh    = gmtime(&tp)->tm_hour   ;
-  mi    = gmtime(&tp)->tm_min    ;
-  name  = getpwuid(getuid())->pw_name;
-
-  proc = strrchr(procpath,'/');
+  long yy    = gmtime(&tp)->tm_year + 1900;
+  long mm    = gmtime(&tp)->tm_mon + 1;
+  long dd    = gmtime(&tp)->tm_mday   ;
+  long hh    = gmtime(&tp)->tm_hour   ;
+  long mi    = gmtime(&tp)->tm_min    ;
+  char *name = getpwuid(getuid())->pw_name;
+
+  char *proc = strrchr(procpath,'/');
   if (proc == 0) proc = procpath;
   else           proc++         ;
 
   strcpy(stat_file, "/pf/m/m214003/local/log/after.log");
 
-  MaxMBytes = (double) memTotal() / 1048576.;
+  double MaxMBytes = (double) memTotal() / 1048576.;
 
-  sf = fopen(stat_file, "a");
+  FILE *sf = fopen(stat_file, "a");
   if ( sf )
     {
       char unknown[] = "";
diff --git a/src/Arith.c b/src/Arith.c
index 5c2277a..56d601c 100644
--- a/src/Arith.c
+++ b/src/Arith.c
@@ -263,6 +263,8 @@ void *Arith(void *argument)
 		  streamInqRecord(streamIDx2, &varID2, &levelID2);
 		  streamReadRecord(streamIDx2, fieldx2->ptr, &nmiss);
                   fieldx2->nmiss = (size_t) nmiss;
+                  if ( varID   != varID2 ) cdoAbort("Internal error, varIDs of input streams differ!");
+                  if ( levelID != levelID2 ) cdoAbort("Internal error, levelIDs of input streams differ!");
 		}
 
 	      if ( filltype == FILL_TS )
diff --git a/src/Arithdays.c b/src/Arithdays.c
index 08bfda5..83c984b 100644
--- a/src/Arithdays.c
+++ b/src/Arithdays.c
@@ -63,9 +63,9 @@ double dayofyear(int calendar, int vdate, int vtime)
   doy += (second+minute*60+hour*3600)/86400.;
 
   if ( cdoVerbose )
-    cdoPrint("%d %d %d %g\n", vdate, vtime, dpy, doy);
+    cdoPrint("vdate, vtime, dpy, doy: %d %d %d %g", vdate, vtime, dpy, doy);
 
-  return (doy);
+  return doy;
 }
 
 
diff --git a/src/CDItest.c b/src/CDItest.c
index 70902a4..8d72bcf 100644
--- a/src/CDItest.c
+++ b/src/CDItest.c
@@ -28,33 +28,22 @@
 
 void *CDItest(void *argument)
 {
-  int NCOPY;
-  int operatorID;
-  int streamID1, streamID2;
-  int n;
   int nrecs;
-  int tsID1, tsID2, recID, varID, levelID;
-  int lcopy = FALSE;
-  int gridsize;
-  int vlistID1, vlistID2 = -1;
+  int recID, varID, levelID;
   int nmiss;
-  int taxisID1, taxisID2 = CDI_UNDEFID;
   int max_copy = 3;
-  double *array = NULL;
   double s_utime, s_stime;
   double e_utime, e_stime;
-  double c_cputime = 0, c_usertime = 0, c_systime = 0;
 
   cdoInitialize(argument);
 
-  NCOPY = cdoOperatorAdd("ncopy",   0, 0, NULL);
+  bool lcopy = false;
+  //bool lcopy = UNCHANGED_RECORD;
 
+  int NCOPY = cdoOperatorAdd("ncopy",   0, 0, NULL);
   UNUSED(NCOPY);
 
-  //  if ( UNCHANGED_RECORD ) lcopy = TRUE;
-
-  operatorID = cdoOperatorID();
-
+  int operatorID = cdoOperatorID();
   UNUSED(operatorID);
 
   //  operatorInputArg("Number of copies");
@@ -62,27 +51,27 @@ void *CDItest(void *argument)
 
   processStartTime(&s_utime, &s_stime);
 
-  n = 0;
+  int n = 0;
   while ( TRUE )
     {
-      streamID1 = streamOpenRead(cdoStreamName(0));
+      int streamID1 = streamOpenRead(cdoStreamName(0));
 
-      vlistID1 = streamInqVlist(streamID1);
-      taxisID1 = vlistInqTaxis(vlistID1);
+      int vlistID1 = streamInqVlist(streamID1);
+      int taxisID1 = vlistInqTaxis(vlistID1);
 
-      streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+      int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
-      vlistID2 = vlistDuplicate(vlistID1);
-      taxisID2 = taxisDuplicate(taxisID1);
+      int vlistID2 = vlistDuplicate(vlistID1);
+      int taxisID2 = taxisDuplicate(taxisID1);
       vlistDefTaxis(vlistID2, taxisID2);
 
       streamDefVlist(streamID2, vlistID2);
 
-      gridsize = vlistGridsizeMax(vlistID1);
-      array = (double*) Malloc(gridsize*sizeof(double));
+      int gridsize = vlistGridsizeMax(vlistID1);
+      double *array = (double*) Malloc(gridsize*sizeof(double));
 
-      tsID1 = 0;
-      tsID2 = 0;
+      int tsID1 = 0;
+      int tsID2 = 0;
       while ( (nrecs = streamInqTimestep(streamID1, tsID1)) )
 	{
 	  taxisCopyTimestep(taxisID2, taxisID1);
@@ -120,9 +109,9 @@ void *CDItest(void *argument)
 
       cdoProcessTime(&e_utime, &e_stime);
 
-      c_usertime = e_utime - s_utime;
-      c_systime  = e_stime - s_stime;
-      c_cputime  = c_usertime + c_systime;
+      double c_usertime = e_utime - s_utime;
+      double c_systime  = e_stime - s_stime;
+      double c_cputime  = c_usertime + c_systime;
 
       s_utime = e_utime;
       s_stime = e_stime;
diff --git a/src/CMOR.c b/src/CMOR.c
index bba174e..37dacd1 100644
--- a/src/CMOR.c
+++ b/src/CMOR.c
@@ -2,10 +2,10 @@
 #include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
-#include <search.h>
-#include <ctype.h>
 
 #if defined(HAVE_LIBCMOR)
+#include <ctype.h>
+#include "uthash.h"
 #include "cmor.h"
 
 struct cc_var
@@ -16,6 +16,13 @@ struct cc_var
   void *data;
 };
 
+struct kv
+{
+  char *key;
+  char *value;
+  UT_hash_handle hh;
+};
+
 static struct cc_var *find_var(int cdi_varID, struct cc_var vars[], int nvars)
 {
   for ( int i = 0; i < nvars; i++ )
@@ -26,161 +33,132 @@ static struct cc_var *find_var(int cdi_varID, struct cc_var vars[], int nvars)
 
 static char *trim(char *s)
 {
-  int n;
   if (s == NULL) return s;
   while ( *s != '\0' && (isspace(*s) || *s == '"') )
     s++;
-  n = strlen(s);
+  int n = strlen(s);
   while ( n > 0 && (isspace(s[n - 1]) || s[n - 1] == '"') )
     n--;
   s[n] = '\0';
   return s;
 }
 
-static ENTRY *hinsert(const char *key, const char *value)
+static void hinsert(struct kv **ht, const char *key, const char *value)
 {
   /* Insert new keys. Do not overwrite values of existing keys. */
-  ENTRY e, *ep;
-
-  e.key = strdup(key);
-  e.data = (void *)strdup(value);
-  ep = hsearch(e, FIND);
-  if ( ep == NULL )
-    {
-      ep = hsearch(e, ENTER);
-    }
-  else
+  struct kv *e, *s;
+  HASH_FIND_STR(*ht, key, s);
+  if ( s == NULL)
     {
-      free(e.key);
-      free(e.data);
+      e = Malloc(sizeof(struct kv));
+      e->key = Malloc(strlen(key) + 1);
+      e->value = Malloc(strlen(value) + 1);
+      strcpy(e->key, key);
+      strcpy(e->value, value);
+      HASH_ADD_KEYPTR(hh, *ht, e->key, strlen(e->key), e);
     }
-  return ep;
 }
 
-static ENTRY *hreplace(const char *key, const char *value)
+static void hreplace(struct kv **ht, const char *key, const char *value)
 {
   /* Overwrites values of existing keys. */
-  ENTRY e, *ep;
-
-  e.key = strdup(key);
-  e.data = (void *)strdup(value);
-  ep = hsearch(e, FIND);
-  if ( ep == NULL )
-    {
-      ep = hsearch(e, ENTER);
-    }
-  else
+  struct kv *s;
+  HASH_FIND_STR(*ht, key, s);
+  if ( s )
     {
-      free(e.key);
-      free(ep->data);
-      ep->data = e.data;
+      HASH_DEL(*ht, s);
+      Free(s->key);
+      Free(s->value);
+      Free(s);
     }
-  return ep;
+  hinsert(ht, key, value);
 }
 
-static ENTRY *parse_kv(char *kvstr)
+static void parse_kv(struct kv **ht, char *kvstr)
 {
   char *key = trim(strtok(kvstr, "="));
   char *value = trim(strtok(NULL, "="));
-  if ( key == NULL || value == NULL )
-    return NULL;
-  return hinsert(key, value);
+  if ( key && value )
+    hinsert(ht, key, value);
 }
 
-static int parse_kv_file(const char *filename, int verbose)
+static int parse_kv_file(struct kv **ht, const char *filename, int verbose)
 {
-  FILE *fp;
-  char line[CMOR_MAX_STRING], *comment;
-
-  fp = fopen(filename, "r");
+  FILE *fp = fopen(filename, "r");
   if ( fp == NULL )
     {
       if ( verbose )
         cdoWarning("cannot open '%s'", filename);
       return 1;
     }
+
+  char line[CMOR_MAX_STRING];
   while ( fgets(line, sizeof(line), fp) != NULL )
     {
-      comment = strchr(line, '#');
+      char *comment = strchr(line, '#');
       if ( comment ) *comment = '\0';
-      parse_kv(line);
+      parse_kv(ht, line);
     }
   fclose(fp);
   return 0;
 }
 
-static void parse_kv_cmdline(int nparams, char **params)
+static void parse_kv_cmdline(struct kv **ht, int nparams, char **params)
 {
-  int i, j, k, size;
-  char *p;
-
   /* Assume key = value pairs. That is, if params[i] contains no '='
    * then treat it as if it belongs to the value of params[i-1],
    * separated by a ','.*/
-  i = 0;
+  int i = 0;
   while ( i < nparams )
     {
-      j = 1;
-      size = strlen(params[i]) + 1;
+      int j = 1;
+      int size = strlen(params[i]) + 1;
       while ( i + j < nparams && strchr(params[i + j], '=') == NULL )
         {
           size += strlen(params[i + j]) + 1;
           j++;
         }
-      p = (char *) Malloc(size);
+      char *p = (char *) Malloc(size);
       strcpy(p, params[i]);
-      for (k = 1; k < j; k++)
+      for (int k = 1; k < j; k++)
         {
           strcat(p, ",");
           strcat(p, params[i + k]);
         }
-      parse_kv(p);
-      free(p);
+      parse_kv(ht, p);
+      Free(p);
       i += j;
     }
 }
 
-static char *get_val(char *key, char *def)
+static char *get_val(struct kv **ht, char *key, char *def)
 {
-  ENTRY e, *ep;
-
-  e.key = key;
-  ep = hsearch(e, FIND);
-  if ( ep )
-    return (char *)ep->data;
-  else
-    return def;
+  struct kv *e;
+  HASH_FIND_STR(*ht, key, e);
+  return e ? e->value : def;
 }
 
-static char *substitute(char *word)
+static char *substitute(struct kv **ht, char *word)
 {
-  ENTRY e, *ep;
-  char *key;
-
-  key = (char *) Malloc(strlen(word) + 12);
+  struct kv *e;
+  char *key = (char *) Malloc(strlen(word) + 12);
   sprintf(key, "substitute_%s", word);
-  e.key = key;
-  ep = hsearch(e, FIND);
+  HASH_FIND_STR(*ht, key, e);
   Free(key);
-  if ( ep )
-    return (char *)ep->data;
-  else
-    return word;
+  return e ? e->value : word;
 }
 
-static void dump_global_attributes(int streamID)
+static void dump_global_attributes(struct kv **ht, int streamID)
 {
-  int i, natts;
-  char name[CDI_MAX_NAME];
-  char buffer[8];
-  char *value;
-  int type, len;
+  int natts;
   int vlistID = streamInqVlist(streamID);
-
   vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
-  for ( i = 0; i < natts; i++ )
+  for ( int i = 0; i < natts; i++ )
     {
-      value = NULL;
+      char name[CDI_MAX_NAME];
+      char *value = NULL;
+      char buffer[8];
+      int type, len;
       vlistInqAtt(vlistID, CDI_GLOBAL, i, name, &type, &len);
       switch ( type )
         {
@@ -200,72 +178,89 @@ static void dump_global_attributes(int streamID)
           snprintf(value, CDI_MAX_NAME, "%e", *(double *)buffer);
           break;
         default:
-          printf("Unsupported type %i name %s\n", type, name);
+          cdoWarning("Unsupported type %i name %s\n", type, name);
         }
-      hinsert(name, value);
+      hinsert(ht, name, value);
       if ( value ) Free(value);
     }
 }
 
-static void dump_special_attributes(int streamID)
+static void dump_special_attributes(struct kv **ht, int streamID)
 {
-  int fileID;
-  size_t historysize;
-  char *history, *new_history;
-  const char *value;
   int vlistID = streamInqVlist(streamID);
+  int fileID = pstreamFileID(streamID);
+  size_t old_historysize;
+  char *new_history = get_val(ht, "history", "");
+  size_t historysize;
+  int natts;
+  vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
+  if ( natts > 0 )
+    old_historysize = (size_t) streamInqHistorySize(fileID);
+  else
+    old_historysize = 0;
+
+  if ( old_historysize )
+    {
+      historysize = old_historysize;
+      if ( new_history )
+        historysize += strlen(new_history) + 1;
+    }
+  else
+    {
+      historysize = strlen(new_history);
+    }
 
-  /* Any new history will be appended to the existing history. */
-  fileID = pstreamFileID(streamID);
-  historysize = (size_t) streamInqHistorySize(fileID);
   if ( historysize )
     {
-      new_history = get_val("history", NULL);
-      if ( new_history ) historysize += strlen(new_history) + 1;
-      history = Malloc(historysize + 1);
+      char *history = Malloc(historysize + 1);
       memset(history, 0, historysize + 1);
-      streamInqHistoryString(fileID, history);
-      if ( new_history )
+      if ( old_historysize )
+        {
+          streamInqHistoryString(fileID, history);
+          if ( new_history )
+            {
+              strcat(history, " ");
+              strcat(history, new_history);
+            }
+        }
+      else
         {
-          strcat(history, " ");
-          strcat(history, new_history);
+          strcpy(history, new_history);
         }
-      hreplace("history", history);
+      hreplace(ht, "history", history);
       Free(history);
     }
 
-  value = institutInqLongnamePtr(vlistInqVarInstitut(vlistID, 0));
-  if ( value ) hinsert("institution", value);
-
+  const char *value = institutInqLongnamePtr(vlistInqVarInstitut(vlistID, 0));
+  if ( value ) hinsert(ht, "institution", value);
   value = modelInqNamePtr(vlistInqVarModel(vlistID, 0));
-  if ( value ) hinsert("source", value);
+  if ( value ) hinsert(ht, "source", value);
 }
 
-static void read_config_files(void)
+static void read_config_files(struct kv **ht)
 {
-  char *info_files;
-  char *filename;
-  char *home;
-  const char *dotconfig = ".cdocmorinfo";
-
   /* Files from info key in command line. */
-  info_files = get_val("info", "");
-  filename = strtok(info_files, ",");
+  char *info = get_val(ht, "info", "");
+  char *infoc = Malloc(strlen(info) + 1);
+  strcpy(infoc, info);
+  char *filename = strtok(infoc, ",");
   while ( filename != NULL )
     {
-      parse_kv_file(trim(filename), 1);
+      parse_kv_file(ht, trim(filename), 1);
       filename = strtok(NULL, ",");
     }
+  Free(infoc);
 
   /* Config file in user's $HOME directory. */
-  home = getenv("HOME");
+  char *home = getenv("HOME");
+  const char *dotconfig = ".cdocmorinfo";
   filename = Malloc(strlen(home) + strlen(dotconfig) + 2);
   sprintf(filename, "%s/%s", home, dotconfig);
-  parse_kv_file(filename, 0);
+  parse_kv_file(ht, filename, 0);
   Free(filename);
 
   /* System wide configuration. */
-  parse_kv_file("/etc/cdocmor.info", 0);
+  parse_kv_file(ht, "/etc/cdocmor.info", 0);
 }
 
 static int in_list(char **list, const char *needle)
@@ -276,45 +271,37 @@ static int in_list(char **list, const char *needle)
   return 0;
 }
 
-static void setup(int streamID, char *table)
+static void setup(struct kv **ht, int streamID, char *table)
 {
-  char *chunk;
-  char *logfile;
-  int netcdf_file_action, exit_control;
-  int set_verbosity;
-  int create_subdirectories;
-  int *month_lengths;
-  int table_id;
-  int taxisID = vlistInqTaxis(streamInqVlist(streamID));
-  char *calendar;
-  double branch_time = atof(get_val("branch_time", "0.0"));
-
-  chunk = get_val("chunk", "replace");
+  int netcdf_file_action;
+  char *chunk = get_val(ht, "chunk", "replace");
   if ( strcasecmp(chunk, "replace") == 0 )
     netcdf_file_action = CMOR_REPLACE;
   else if ( strcasecmp(chunk, "append") == 0 )
     netcdf_file_action = CMOR_APPEND;
 
-  set_verbosity = CMOR_NORMAL;
-  if ( strcasecmp(get_val("set_verbosity", ""), "CMOR_QUIET") == 0 )
+  int set_verbosity = CMOR_NORMAL;
+  if ( strcasecmp(get_val(ht, "set_verbosity", ""), "CMOR_QUIET") == 0 )
     set_verbosity = CMOR_QUIET;
 
-  exit_control = CMOR_NORMAL;
-  if ( strcasecmp(get_val("exit_control", ""), "CMOR_EXIT_ON_MAJOR") == 0 )
+  int exit_control = CMOR_NORMAL;
+  if ( strcasecmp(get_val(ht, "exit_control", ""), "CMOR_EXIT_ON_MAJOR") == 0 )
     exit_control = CMOR_EXIT_ON_MAJOR;
-  if ( strcasecmp(get_val("exit_control", ""), "CMOR_EXIT_ON_WARNING") == 0 )
+  if ( strcasecmp(get_val(ht, "exit_control", ""), "CMOR_EXIT_ON_WARNING")
+       == 0 )
     exit_control = CMOR_EXIT_ON_WARNING;
 
-  logfile = get_val("logfile", NULL);
-
-  create_subdirectories = atoi(get_val("create_subdirectories", "0"));
-  cmor_setup(get_val("inpath", "/usr/share/cmor/"),
+  char *logfile = get_val(ht, "logfile", NULL);
+  int create_subdirectories = atoi(get_val(ht, "create_subdirectories", "0"));
+  cmor_setup(get_val(ht, "inpath", "/usr/share/cmor/"),
              &netcdf_file_action,
              &set_verbosity,
              &exit_control,
              logfile,
              &create_subdirectories);
 
+  char *calendar;
+  int taxisID = vlistInqTaxis(streamInqVlist(streamID));
   switch ( taxisInqCalendar(taxisID) )
     {
     case CALENDAR_STANDARD:
@@ -336,10 +323,12 @@ static void setup(int streamID, char *table)
       cdoAbort("Unsupported calendar type.");
     }
 
-  if ( get_val("month_lengths", NULL) )
+  int *month_lengths;
+  char *ml = get_val(ht, "month_lengths", NULL);
+  if ( ml )
     {
-      char *month_lengths_str = strdup(get_val("month_lengths", ""));
-      char *month_str = strtok(month_lengths_str, ",");
+      char *mlc = Malloc(strlen(ml) + 1);
+      char *month_str = strtok(mlc, ",");
       int month = 0;
       month_lengths = Malloc(12 * sizeof(int));
       while ( month < 12 && month_str != NULL )
@@ -347,6 +336,7 @@ static void setup(int streamID, char *table)
           month_lengths[month++] = atoi(month_str);
           month_str = strtok(NULL, ",");
         }
+      Free(mlc);
       if ( month != 12 )
         cdoAbort("Invalid format for month_lengths");
     }
@@ -355,53 +345,42 @@ static void setup(int streamID, char *table)
       month_lengths = NULL;
     }
 
-  cmor_dataset(get_val("outpath", "./"),
-               get_val("experiment_id", ""),
-               get_val("institution", ""),
-               get_val("source", ""),
+  double branch_time = atof(get_val(ht, "branch_time", "0.0"));
+  cmor_dataset(get_val(ht, "outpath", "./"),
+               get_val(ht, "experiment_id", ""),
+               get_val(ht, "institution", ""),
+               get_val(ht, "source", ""),
                calendar,
-               atoi(get_val("realization", "1")),
-               get_val("contact", ""),
-               get_val("history", ""),
-               get_val("comment", ""),
-               get_val("references", ""),
-               atoi(get_val("leap_year", "0")),
-               atoi(get_val("leap_month", "0")),
+               atoi(get_val(ht, "realization", "1")),
+               get_val(ht, "contact", ""),
+               get_val(ht, "history", ""),
+               get_val(ht, "comment", ""),
+               get_val(ht, "references", ""),
+               atoi(get_val(ht, "leap_year", "0")),
+               atoi(get_val(ht, "leap_month", "0")),
                month_lengths,
-               get_val("model_id", ""),
-               get_val("forcing", ""),
-               atoi(get_val("initialization_method", "1")),
-               atoi(get_val("physics_version", "1")),
-               get_val("institute_id", ""),
-               get_val("parent_experiment_id", ""),
+               get_val(ht, "model_id", ""),
+               get_val(ht, "forcing", ""),
+               atoi(get_val(ht, "initialization_method", "1")),
+               atoi(get_val(ht, "physics_version", "1")),
+               get_val(ht, "institute_id", ""),
+               get_val(ht, "parent_experiment_id", ""),
                &branch_time,
-               get_val("parent_experiment_rip", ""));
+               get_val(ht, "parent_experiment_rip", ""));
 
+  int table_id;
   cmor_load_table(table, &table_id);
   cmor_set_table(table_id);
 }
 
-static void define_variables(int streamID, struct cc_var vars[], int *nvars)
+static void define_variables(struct kv **ht, int streamID,
+                             struct cc_var vars[], int *nvars)
 {
   int vlistID = streamInqVlist(streamID);
   int taxisID = vlistInqTaxis(vlistID);
-  size_t gridsize = vlistGridsizeMax(vlistID);
-  struct cc_var *var;
-  int varID, gridID;
-  char name[CDI_MAX_NAME], units[CDI_MAX_NAME];
-  int length;
-  double *coord_vals, *cell_bounds;
-  int ndims, levels;
-  char missing_value[sizeof(double)];
-  double tolerance = 1e-4;
-  int axis_ids[CMOR_MAX_AXES];
-  char *select_vars = get_val("var", NULL);
-  int year, month, day, hour, minute, second;
-  int timeunit = taxisInqTunit(taxisID);
   char taxis_units[CMOR_MAX_STRING];
-  char **name_list, *var_name;
-  int i;
-
+  int timeunit = taxisInqTunit(taxisID);
+  int year, month, day, hour, minute, second;
   cdiDecodeDate(taxisInqRdate(taxisID), &year, &month, &day);
   cdiDecodeTime(taxisInqRtime(taxisID), &hour, &minute, &second);
   if ( timeunit == TUNIT_QUARTER || timeunit == TUNIT_30MINUTES )
@@ -415,11 +394,13 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
           tunitNamePtr(timeunit), year, month, day, hour,
           minute, second);
 
+  char **name_list;
+  char *select_vars = get_val(ht, "var", NULL);
   if ( select_vars )
     {
       name_list = Malloc((strlen(select_vars) + 1) * sizeof(char *));
-      var_name = strtok(select_vars, ",");
-      i = 0;
+      char *var_name = strtok(select_vars, ",");
+      int i = 0;
       while ( var_name != NULL )
         {
           name_list[i++] = trim(var_name);
@@ -433,19 +414,17 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
     }
 
   *nvars = 0;
-  for ( varID = 0; varID < vlistNvars(vlistID); varID++ )
+  for ( int varID = 0; varID < vlistNvars(vlistID); varID++ )
     {
+      char name[CDI_MAX_NAME];
+      int axis_ids[CMOR_MAX_AXES];
       vlistInqVarName(vlistID, varID, name);
       if ( name_list == NULL || in_list(name_list, name) )
         {
-          var = &vars[(*nvars)++];
-          var->cdi_varID = varID;
-          gridID = vlistInqVarGrid(vlistID, varID);
-          ndims = 0;
-
+          int ndims = 0;
           /* Time-Axis */
           cmor_axis(&axis_ids[ndims++],
-                    substitute("time"),
+                    substitute(ht, "time"),
                     taxis_units,
                     0,
                     NULL,
@@ -456,7 +435,9 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
 
           /* Z-Axis */
           int zaxisID = vlistInqVarZaxis(vlistID, varID);
-          levels = zaxisInqSize(zaxisID);
+          int levels = zaxisInqSize(zaxisID);
+          char units[CDI_MAX_NAME];
+          double *coord_vals;
           if ( zaxisInqType(zaxisID) != ZAXIS_SURFACE )
             {
               coord_vals = Malloc(levels * sizeof(double));
@@ -464,7 +445,7 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
               zaxisInqName(zaxisID, name);
               zaxisInqUnits(zaxisID, units);
               cmor_axis(&axis_ids[ndims++],
-                        substitute(name),
+                        substitute(ht, name),
                         units,
                         levels,
                         (void *)coord_vals,
@@ -475,15 +456,21 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
             }
 
           /* Y-Axis */
+          int gridID = vlistInqVarGrid(vlistID, varID);
           gridInqYname(gridID, name);
           gridInqYunits(gridID, units);
-          length = gridInqYsize(gridID);
+          int length = gridInqYsize(gridID);
           coord_vals = Malloc(length * sizeof(double));
           gridInqYvals(gridID, coord_vals);
-          cell_bounds = Malloc(2 * length * sizeof(double));
-          gridInqYbounds(gridID, cell_bounds);
+          double *cell_bounds = Malloc(2 * length * sizeof(double));
+          int nbounds = gridInqYbounds(gridID, cell_bounds);
+          if ( nbounds != 2 * length )
+            {
+              Free(cell_bounds);
+              cell_bounds = NULL;
+            }
           cmor_axis(&axis_ids[ndims++],
-                    substitute(name),
+                    substitute(ht, name),
                     units,
                     length,
                     (void *)coord_vals,
@@ -499,9 +486,14 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
           coord_vals = Malloc(length * sizeof(double));
           gridInqXvals(gridID, coord_vals);
           cell_bounds = Malloc(2 * length * sizeof(double));
-          gridInqXbounds(gridID, cell_bounds);
+          nbounds = gridInqXbounds(gridID, cell_bounds);
+          if ( nbounds != 2 * length )
+            {
+              Free(cell_bounds);
+              cell_bounds = NULL;
+            }
           cmor_axis(&axis_ids[ndims++],
-                    substitute(name),
+                    substitute(ht, name),
                     units,
                     length,
                     (void *)coord_vals,
@@ -513,6 +505,11 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
           /* Variable */
           vlistInqVarUnits(vlistID, varID, units);
           vlistInqVarName(vlistID, varID, name);
+          char missing_value[sizeof(double)];
+          double tolerance = 1e-4;
+          size_t gridsize = vlistGridsizeMax(vlistID);
+          struct cc_var *var = &vars[(*nvars)++];
+          var->cdi_varID = varID;
           if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
             {
               var->datatype = 'f';
@@ -526,7 +523,7 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
               var->data = Malloc(gridsize * levels * sizeof(double));
             }
           cmor_variable(&var->cmor_varID,
-                        substitute(name),
+                        substitute(ht, name),
                         units,
                         ndims,
                         axis_ids,
@@ -544,28 +541,9 @@ static void define_variables(int streamID, struct cc_var vars[], int *nvars)
 
 static void write_variables(int streamID, struct cc_var vars[], int nvars)
 {
-  struct cc_var *var;
   int vlistID = streamInqVlist(streamID);
   int taxisID = vlistInqTaxis(vlistID);
-  size_t gridsize = vlistGridsizeMax(vlistID);
-  double time_val;
-  double time_bnds[2];
-  double *time_bndsp;
-  int has_bnds = taxisHasBounds(taxisID);
-  int tsID;
-  int vdate0b, vdate1b;
-  int vtime0b, vtime1b;
-  juldate_t juldate, r_juldate;
-  int calendar = taxisInqCalendar(taxisID);
   int tunitsec;
-  int nrecs;
-  int varID, levelID;
-  int nmiss;
-  double *buffer;
-  int i;
-
-  buffer = (double *) Malloc(gridsize * sizeof(double));
-
   switch ( taxisInqTunit(taxisID) )
     {
     case TUNIT_MINUTE: tunitsec = 60; break;
@@ -574,20 +552,28 @@ static void write_variables(int streamID, struct cc_var vars[], int nvars)
     default: tunitsec = 3600;
     }
 
-  r_juldate = juldate_encode(calendar,
-                             taxisInqRdate(taxisID),
-                             taxisInqRtime(taxisID));
-  tsID = 0;
+  int calendar = taxisInqCalendar(taxisID);
+  juldate_t r_juldate = juldate_encode(calendar,
+                                       taxisInqRdate(taxisID),
+                                       taxisInqRtime(taxisID));
+  size_t gridsize = vlistGridsizeMax(vlistID);
+  double *buffer = (double *) Malloc(gridsize * sizeof(double));
+  int tsID = 0;
+  int nrecs;
   while ( (nrecs = streamInqTimestep(streamID, tsID++)) )
     {
-      juldate = juldate_encode(calendar,
-                               taxisInqVdate(taxisID),
-                               taxisInqVtime(taxisID));
+      double time_bnds[2];
+      double *time_bndsp;
+      double time_val;
+      juldate_t juldate = juldate_encode(calendar,
+                                         taxisInqVdate(taxisID),
+                                         taxisInqVtime(taxisID));
       time_val = juldate_to_seconds(juldate_sub(juldate, r_juldate))
         / tunitsec;
 
-      if ( has_bnds )
+      if ( taxisHasBounds(taxisID) )
         {
+          int vdate0b, vdate1b, vtime0b, vtime1b;
           taxisInqVdateBounds(taxisID, &vdate0b, &vdate1b);
           taxisInqVtimeBounds(taxisID, &vtime0b, &vtime1b);
 
@@ -607,14 +593,16 @@ static void write_variables(int streamID, struct cc_var vars[], int nvars)
 
       while ( nrecs-- )
         {
+          int varID, levelID;
           streamInqRecord(streamID, &varID, &levelID);
-          var = find_var(varID, vars, nvars);
+          struct cc_var *var = find_var(varID, vars, nvars);
           if ( var )
             {
+              int nmiss;
               if ( var->datatype == 'f' )
                 {
                   streamReadRecord(streamID, buffer, &nmiss);
-                  for ( i = 0; i < gridsize; i++ )
+                  for ( size_t i = 0; i < gridsize; i++ )
                     ((float *)var->data)[gridsize * levelID + i] =
                       (float)buffer[i];
                 }
@@ -627,7 +615,7 @@ static void write_variables(int streamID, struct cc_var vars[], int nvars)
             }
         }
 
-      for ( i = 0; i < nvars; i++ )
+      for ( int i = 0; i < nvars; i++ )
         cmor_write(vars[i].cmor_varID,
                    vars[i].data,
                    vars[i].datatype,
@@ -648,39 +636,42 @@ void *CMOR(void *argument)
 #if defined(HAVE_LIBCMOR)
   int nparams = operatorArgc();
   char **params = operatorArgv();
-  int nvars, nvars_max;
-  int streamID;
-  struct cc_var *vars;
-
+  struct kv *ht = NULL;
   if ( nparams < 1 ) cdoAbort("Too few arguments!");
 
-  hcreate(100);
-
   /* Command line config has highest priority. */
-  parse_kv_cmdline(nparams - 1, &params[1]);
+  parse_kv_cmdline(&ht, nparams - 1, &params[1]);
 
   /* Config files are read with descending priority. */
-  read_config_files();
+  read_config_files(&ht);
 
-  streamID = streamOpenRead(cdoStreamName(0));
+  int streamID = streamOpenRead(cdoStreamName(0));
   /* Existing attributes have lowest priority. */
-  dump_global_attributes(streamID);
-  dump_special_attributes(streamID);
-
-  nvars_max = vlistNvars(streamInqVlist(streamID));
-  vars = (struct cc_var *) Malloc(nvars_max * sizeof(struct cc_var));
-
-  setup(streamID, params[0]);
-  define_variables(streamID, vars, &nvars);
+  dump_global_attributes(&ht, streamID);
+  dump_special_attributes(&ht, streamID);
+
+  int nvars;
+  int nvars_max = vlistNvars(streamInqVlist(streamID));
+  struct cc_var *vars = (struct cc_var *) Malloc(nvars_max
+                                                 * sizeof(struct cc_var));
+  setup(&ht, streamID, params[0]);
+  define_variables(&ht, streamID, vars, &nvars);
   write_variables(streamID, vars, nvars);
 
   streamClose(streamID);
   cmor_close();
 
-  hdestroy();
   for ( int i = 0; i < nvars; i++ )
     Free(vars[i].data);
   Free(vars);
+
+  struct kv *s, *tmp;
+  HASH_ITER(hh, ht, s, tmp)
+    {
+      Free(s->key);
+      Free(s->value);
+      Free(s);
+    }
 #else
   cdoWarning("CMOR support not compiled in!");
 #endif
diff --git a/src/Cat.c b/src/Cat.c
index ceb8e7a..ed2cece 100644
--- a/src/Cat.c
+++ b/src/Cat.c
@@ -42,8 +42,7 @@ void *Cat(void *argument)
 
   cdoInitialize(argument);
 
-  bool lcopy = false;
-  if ( UNCHANGED_RECORD ) lcopy = true;
+  bool lcopy = UNCHANGED_RECORD;
 
   int timer_cat = timer_new("cat");
   if ( cdoTimer ) timer_start(timer_cat);
diff --git a/src/Collgrid.c b/src/Collgrid.c
index 559dcfe..e5085bc 100644
--- a/src/Collgrid.c
+++ b/src/Collgrid.c
@@ -82,12 +82,12 @@ int cmpxy_gt(const void *s1, const void *s2)
 static
 int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks)
 {
-  int lsouthnorth = TRUE;
+  bool lsouthnorth = true;
+  bool lregular = false;
+  bool lcurvilinear = false;
   int gridID2 = -1;
   int idx;
   int ny, ix, iy, i, j, ij, offset;
-  int lregular = FALSE;
-  int lcurvilinear = FALSE;
   double *xvals2 = NULL, *yvals2 = NULL;
 
   int nx = -1;
@@ -109,9 +109,9 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
       gridID   = vlistGrid(ef[fileID].vlistID, igrid);
       gridtype = gridInqType(gridID);
       if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
-        lregular = TRUE;
+        lregular = true;
       else if ( gridtype == GRID_CURVILINEAR )
-        lcurvilinear = TRUE;
+        lcurvilinear = true;
       else if ( gridtype == GRID_GENERIC && gridInqXsize(gridID) > 0 && gridInqYsize(gridID) > 0 )
         ;
       else
@@ -151,7 +151,7 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
 
           if ( ysize[fileID] > 1 )
             {
-              if ( yvals[fileID][0] > yvals[fileID][ysize[fileID]-1] ) lsouthnorth = FALSE;
+              if ( yvals[fileID][0] > yvals[fileID][ysize[fileID]-1] ) lsouthnorth = false;
             }
         }
       else
@@ -323,10 +323,8 @@ void *Collgrid(void *argument)
   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);
+  if ( !cdoOverwriteMode && fileExists(ofilename) && !userFileOverwrite(ofilename) )
+    cdoAbort("Outputfile %s already exists!", ofilename);
 
   ens_file_t *ef = (ens_file_t*) Malloc(nfiles*sizeof(ens_file_t));
 
@@ -344,10 +342,10 @@ void *Collgrid(void *argument)
     vlistCompare(vlistID1, ef[fileID].vlistID, CMP_NAME | CMP_NLEVEL);
 
   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;
+  bool *vars  = (bool*) Malloc(nvars*sizeof(bool));
+  for ( varID = 0; varID < nvars; varID++ ) vars[varID] = false;
+  bool *vars1  = (bool*) Malloc(nvars*sizeof(bool));
+  for ( varID = 0; varID < nvars; varID++ ) vars1[varID] = false;
 
   int nsel = operatorArgc();
 
@@ -365,7 +363,7 @@ void *Collgrid(void *argument)
 
   if ( nsel == 0 )
     {
-      for ( varID = 0; varID < nvars; varID++ ) vars1[varID] = TRUE;
+      for ( varID = 0; varID < nvars; varID++ ) vars1[varID] = true;
     }
   else
     {
@@ -375,8 +373,8 @@ void *Collgrid(void *argument)
 	for ( int i = 0; i < nsel; i++ )
 	  fprintf(stderr, "name %d = %s\n", i+1, argnames[i]);
 
-      int *selfound = (int*) Malloc(nsel*sizeof(int));
-      for ( int i = 0; i < nsel; i++ ) selfound[i] = FALSE;
+      bool *selfound = (bool*) Malloc(nsel*sizeof(bool));
+      for ( int i = 0; i < nsel; i++ ) selfound[i] = false;
 
       char varname[CDI_MAX_NAME];
       for ( varID = 0; varID < nvars; varID++ )
@@ -387,14 +385,14 @@ void *Collgrid(void *argument)
 	    {
 	      if ( strcmp(argnames[isel], varname) == 0 )
 		{
-		  selfound[isel] = TRUE;
-		  vars1[varID] = TRUE;
+		  selfound[isel] = true;
+		  vars1[varID] = true;
 		}
 	    }
 	}
 
       for ( int isel = 0; isel < nsel; isel++ )
-	if ( selfound[isel] == FALSE )
+	if ( selfound[isel] == false )
 	  cdoAbort("Variable name %s not found!", argnames[isel]);
 
       Free(selfound);
@@ -402,7 +400,7 @@ void *Collgrid(void *argument)
 
   for ( varID = 0; varID < nvars; varID++ )
     {
-      if ( vars1[varID] == TRUE )
+      if ( vars1[varID] )
 	{
 	  int zaxisID  = vlistInqVarZaxis(vlistID1, varID);
 	  int nlevs    = zaxisInqSize(zaxisID);
@@ -435,7 +433,7 @@ void *Collgrid(void *argument)
   //int vlistID2 = vlistDuplicate(vlistID1);
   int nvars2 = vlistNvars(vlistID2);
   // int *vars  = (int*) Malloc(nvars*sizeof(int));
-  //for ( varID = 0; varID < nvars; varID++ ) vars[varID] = FALSE;
+  //for ( varID = 0; varID < nvars; varID++ ) vars[varID] = false;
 
   int ngrids1 = vlistNgrids(vlistID1);
   int ngrids2 = vlistNgrids(vlistID2);
@@ -445,7 +443,7 @@ void *Collgrid(void *argument)
   for ( int fileID = 0; fileID < nfiles; fileID++ )
     gridindex[fileID] = (int*) Malloc(gridsizemax*sizeof(int));
 
-  int ginit = FALSE;
+  bool ginit = false;
   for ( int i2 = 0; i2 < ngrids2; ++i2 )
     {
       int i1;
@@ -454,10 +452,10 @@ void *Collgrid(void *argument)
 
       //   printf("i1 %d i2 %d\n", i1, i2);
 
-      if ( ginit == FALSE )
+      if ( !ginit )
 	{
 	  gridIDs[i2] = genGrid(nfiles, ef, gridindex, i1, nxblocks);
-	  if ( gridIDs[i2] != -1 ) ginit = TRUE;
+	  if ( gridIDs[i2] != -1 ) ginit = true;
 	}
       else
 	gridIDs[i2] = genGrid(nfiles, ef, NULL, i1, nxblocks);
@@ -487,7 +485,7 @@ void *Collgrid(void *argument)
 	{
 	  if ( gridIDs[i] != -1 ) 
 	    {
-	      if ( gridID == vlistGrid(vlistID2, i) ) vars[varID] = TRUE;
+	      if ( gridID == vlistGrid(vlistID2, i) ) vars[varID] = true;
 	      break;
 	    }
 	}
diff --git a/src/Copy.c b/src/Copy.c
index 411ae37..9ac842f 100644
--- a/src/Copy.c
+++ b/src/Copy.c
@@ -43,13 +43,12 @@ void *Copy(void *argument)
 
   cdoInitialize(argument);
 
+  bool lcopy = UNCHANGED_RECORD;
+
                 cdoOperatorAdd("copy",   0, 0, NULL);
   int SELALL  = cdoOperatorAdd("selall", 0, 0, NULL);
   int SZIP    = cdoOperatorAdd("szip",   0, 0, NULL);
 
-  bool lcopy = false;
-  if ( UNCHANGED_RECORD ) lcopy = true;
-
   int operatorID = cdoOperatorID();
 
   if ( operatorID == SZIP )
diff --git a/src/Deltime.c b/src/Deltime.c
index 9dd98ea..2f1f7ed 100644
--- a/src/Deltime.c
+++ b/src/Deltime.c
@@ -25,19 +25,12 @@
 
 void *Deltime(void *argument)
 {
-  int DELDAY, DEL29FEB;
-  int operatorID;
-  int streamID1, streamID2;
-  int tsID, tsID2, nrecs;
+  int nrecs;
   int recID, varID, levelID;
-  int vlistID1, vlistID2;
-  int taxisID1, taxisID2;
   int vdate /*, vtime */;
   int copytimestep;
-  int lcopy = FALSE;
   int gridsize;
   int nmiss;
-  int nfound;
   int year, month, day;
   int dday, dmon;
   double *array = NULL;
@@ -45,12 +38,14 @@ void *Deltime(void *argument)
 
   cdoInitialize(argument);
 
-  DELDAY   = cdoOperatorAdd("delday",   0, 0, NULL);
-  DEL29FEB = cdoOperatorAdd("del29feb", 0, 0, NULL);
+  bool lcopy = UNCHANGED_RECORD;
+
+  int DELDAY   = cdoOperatorAdd("delday",   0, 0, NULL);
+  int DEL29FEB = cdoOperatorAdd("del29feb", 0, 0, NULL);
 
   UNUSED(DELDAY);
 
-  operatorID = cdoOperatorID();
+  int operatorID = cdoOperatorID();
 
   if ( operatorID == DEL29FEB )
     {
@@ -84,19 +79,17 @@ void *Deltime(void *argument)
 
   if ( cdoVerbose ) cdoPrint("delete day %d%s", dday, cmons[dmon]);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
-
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   taxisDefCalendar(taxisID2, CALENDAR_365DAYS);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
@@ -106,9 +99,9 @@ void *Deltime(void *argument)
       array = (double*) Malloc(gridsize*sizeof(double));
     }
       
-  nfound = 0;
-  tsID  = 0;
-  tsID2 = 0;
+  int nfound = 0;
+  int tsID  = 0;
+  int tsID2 = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       vdate = taxisInqVdate(taxisID1);
diff --git a/src/Derivepar.c b/src/Derivepar.c
index c878d96..3aa5261 100644
--- a/src/Derivepar.c
+++ b/src/Derivepar.c
@@ -32,54 +32,17 @@
 
 void MakeGeopotHeight(double *geop, double* gt, double *gq, double *ph, int nhor, int nlev);
 
-
-void minmaxval(long nvals, double *array, int *imiss, double *minval, double *maxval)
-{
-  long i;
-  double xmin =  DBL_MAX;
-  double xmax = -DBL_MAX;
-
-  if ( imiss )
-    {
-      for ( i = 0; i < nvals; ++i )
-	{
-	  if ( ! imiss[i] )
-	    {
-	      if      ( array[i] > xmax ) xmax = array[i];
-	      else if ( array[i] < xmin ) xmin = array[i];
-	    }
-	}
-    }
-  else
-    {
-      xmin = array[0];
-      xmax = array[0];
-      for ( i = 1; i < nvals; ++i )
-	{
-	  if      ( array[i] > xmax ) xmax = array[i];
-	  else if ( array[i] < xmin ) xmin = array[i];
-	}
-    }
-
-  *minval = xmin;
-  *maxval = xmax;
-}
-
+double *vlist_hybrid_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlevf);
 
 void *Derivepar(void *argument)
 {
   int mode;
   enum {ECHAM_MODE, WMO_MODE};
-  int streamID2;
-  int vlistID2;
   int recID, nrecs;
   int i, offset;
-  int tsID, varID, levelID;
-  int nvars;
-  int zaxisIDh = -1, nzaxis;
+  int varID, levelID;
   int zaxisID;
   int nlevel;
-  int nvct;
   int surfaceID = -1;
   int sgeopotID = -1, geopotID = -1, tempID = -1, humID = -1, psID = -1, lnpsID = -1, presID = -1, gheightID = -1;
   // int clwcID = -1, ciwcID = -1;
@@ -88,26 +51,16 @@ void *Derivepar(void *argument)
   char paramstr[32];
   char varname[CDI_MAX_NAME], stdname[CDI_MAX_NAME];
   double *single2;
-  int taxisID1, taxisID2;
-  int lhavevct;
-  int nhlevf = 0;
-  double *vct = NULL;
-  double *sgeopot = NULL, *ps = NULL, *temp = NULL, *hum = NULL;
   // double *lwater = NULL, *iwater = NULL;
-  double *gheight = NULL;
-  double *sealevelpressure = NULL;
   int nmiss, nmissout = 0;
-  double *array = NULL;
-  double *half_press = NULL;
   double *full_press = NULL;
   double minval, maxval;
   int instNum, tableNum;
-  int useTable;
   gribcode_t gribcodes = {0};
 
   cdoInitialize(argument);
 
-  int GHEIGHT          = cdoOperatorAdd("gheight",   0, 0, NULL);
+  int GHEIGHT          = cdoOperatorAdd("gheight",            0, 0, NULL);
   int SEALEVELPRESSURE = cdoOperatorAdd("sealevelpressure",   0, 0, NULL);
 
   int operatorID = cdoOperatorID();
@@ -122,66 +75,28 @@ void *Derivepar(void *argument)
  
   int gridsize = vlist_check_gridsize(vlistID1);
 
-  nzaxis  = vlistNzaxis(vlistID1);
-  lhavevct = FALSE;
+  int zaxisIDh = -1;
+  int nvct = 0;
+  int nhlevf = 0;
+  double *vct = vlist_hybrid_vct(vlistID1, &zaxisIDh, &nvct, &nhlevf);
 
   if ( cdoVerbose )
-    cdoPrint("nzaxis: %d", nzaxis);
-
-  for ( i = 0; i < nzaxis; i++ )
-    {
-      zaxisID = vlistZaxis(vlistID1, i);
-      nlevel  = zaxisInqSize(zaxisID);
-      if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID )
-	{
-	  if ( nlevel > 1 )
-	    {
-	      nvct = zaxisInqVctSize(zaxisID);
-
-              if ( cdoVerbose )
-                cdoPrint("i: %d, vct size of zaxisID %d = %d", i, zaxisID, nvct);
-
-	      if ( nlevel == (nvct/2 - 1) )
-		{
-		  if ( lhavevct == FALSE )
-		    {
-		      lhavevct = TRUE;
-		      zaxisIDh = zaxisID;
-		      nhlevf   = nlevel;
-	      
-                      if ( cdoVerbose )
-                        cdoPrint("lhavevct=TRUE  zaxisIDh = %d, nhlevf   = %d", zaxisIDh, nlevel);
- 
-		      vct = (double*) Malloc(nvct*sizeof(double));
-		      zaxisInqVct(zaxisID, vct);
-
-		      if ( cdoVerbose )
-			for ( i = 0; i < nvct/2; ++i )
-			  cdoPrint("vct: %5d %25.17f %25.17f", i, vct[i], vct[nvct/2+i]);
-		    }
-		}
-              else 
-                {
-		  if ( cdoVerbose )
-		    cdoPrint("nlevel = (nvct/2 - 1): nlevel = %d", nlevel);
-                }
-	    }
-	}
-    }
+    for ( i = 0; i < nvct/2; ++i )
+      cdoPrint("vct: %5d %25.17f %25.17f", i, vct[i], vct[nvct/2+i]);
 
   if ( zaxisIDh == -1 )
     cdoAbort("No 3D variable with hybrid sigma pressure coordinate found!");
 
-  nvars = vlistNvars(vlistID1);
+  int nvars = vlistNvars(vlistID1);
 
-  useTable = FALSE;
+  bool useTable = false;
   for ( varID = 0; varID < nvars; varID++ )
     {
       tableNum = tableInqNum(vlistInqVarTable(vlistID1, varID));
 
       if ( tableNum > 0  && tableNum != 255 )
 	{
-	  useTable = TRUE;
+	  useTable = true;
 	  break;
 	}
     }
@@ -283,16 +198,18 @@ void *Derivepar(void *argument)
 
   if ( tempID == -1 ) cdoAbort("%s not found!", var_stdname(air_temperature));
 
-  array   = (double*) Malloc(gridsize*sizeof(double));
-  sgeopot = (double*) Malloc(gridsize*sizeof(double));
-  ps      = (double*) Malloc(gridsize*sizeof(double));
-  temp    = (double*) Malloc(gridsize*nhlevf*sizeof(double));
+  double *array   = (double*) Malloc(gridsize*sizeof(double));
+  double *sgeopot = (double*) Malloc(gridsize*sizeof(double));
+  double *ps      = (double*) Malloc(gridsize*sizeof(double));
+  double *temp    = (double*) Malloc(gridsize*nhlevf*sizeof(double));
 
   // lwater = (double*) Malloc(gridsize*nhlevf*sizeof(double));
   // iwater = (double*) Malloc(gridsize*nhlevf*sizeof(double));
 
-  half_press = (double*) Malloc(gridsize*(nhlevf+1)*sizeof(double));
+  double *half_press = (double*) Malloc(gridsize*(nhlevf+1)*sizeof(double));
 
+  double *hum = NULL;
+  double *gheight = NULL;
   if ( operatorID == GHEIGHT )
     {
       if ( humID == -1 )
@@ -303,6 +220,7 @@ void *Derivepar(void *argument)
       gheight = (double*) Malloc(gridsize*(nhlevf+1)*sizeof(double));
     }
   
+  double *sealevelpressure = NULL;
   if ( operatorID == SEALEVELPRESSURE )
     {
       full_press   = (double*) Malloc(gridsize*nhlevf*sizeof(double));
@@ -338,7 +256,7 @@ void *Derivepar(void *argument)
 	cdoPrint("using %s", var_stdname(surface_air_pressure));
     }
 
-  vlistID2 = vlistCreate();
+  int vlistID2 = vlistCreate();
 
   int var_id = -1;
 
@@ -360,15 +278,15 @@ void *Derivepar(void *argument)
   vlistDefVarStdname(vlistID2, varID, var_stdname(var_id));
   vlistDefVarUnits(vlistID2, varID, var_units(var_id));
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Diff.c b/src/Diff.c
index 9244412..d20fece 100644
--- a/src/Diff.c
+++ b/src/Diff.c
@@ -30,25 +30,16 @@
 
 void *Diff(void *argument)
 {
-  int lhead = TRUE;
-  int i;
-  int varID1, varID2, recID;
-  int ndiff;
-  int code, param;
-  int gridID, zaxisID;
-  int checkrel;
+  bool lhead = true;
   int nrecs, nrecs2;
+  int varID1, varID2;
   int levelID;
-  int dsgn, zero;
   int nmiss1, nmiss2;
   int ndrec = 0, nd2rec = 0, ngrec = 0;
   char varname[CDI_MAX_NAME];
   char paramstr[32];
   char vdatestr[32], vtimestr[32];
-  double absdiff;
   double abslim = 0., abslim2 = 1.e-3, rellim = 1.0;
-  double absm, relm;
-  double missval1, missval2;
 
   cdoInitialize(argument);
 
@@ -60,9 +51,9 @@ void *Diff(void *argument)
   int operatorID = cdoOperatorID();
 
   if ( operatorArgc() >= 1 ) abslim = parameter2double(operatorArgv()[0]);
-  if ( abslim < -1.e33 || abslim > 1.e+33 ) cdoAbort("Abs. limit out of range\n");
+  if ( abslim < -1.e33 || abslim > 1.e+33 ) cdoAbort("Abs. limit out of range!");
   if ( operatorArgc() == 2 ) rellim = parameter2double(operatorArgv()[1]);
-  if ( rellim < -1.e33 || rellim > 1.e+33 ) cdoAbort("Rel. limit out of range\n");
+  if ( rellim < -1.e33 || rellim > 1.e+33 ) cdoAbort("Rel. limit out of range!");
 
   int streamID1 = streamOpenRead(cdoStreamName(0));
   int streamID2 = streamOpenRead(cdoStreamName(1));
@@ -93,36 +84,37 @@ void *Diff(void *argument)
 
       if ( nrecs == 0 || nrecs2 == 0 ) break;
 
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID1, &levelID);
 	  streamInqRecord(streamID2, &varID2, &levelID);
 
 	  indg += 1;
 
-	  param    = vlistInqVarParam(vlistID1, varID1);
-	  code     = vlistInqVarCode(vlistID1, varID1);
-	  gridID   = vlistInqVarGrid(vlistID1, varID1);
-	  zaxisID  = vlistInqVarZaxis(vlistID1, varID1);
-	  gridsize = gridInqSize(gridID);
-	  missval1 = vlistInqVarMissval(vlistID1, varID1);
-	  missval2 = vlistInqVarMissval(vlistID2, varID2);
+	  int param    = vlistInqVarParam(vlistID1, varID1);
+	  int code     = vlistInqVarCode(vlistID1, varID1);
+	  int gridID   = vlistInqVarGrid(vlistID1, varID1);
+	  int zaxisID  = vlistInqVarZaxis(vlistID1, varID1);
+	  int gridsize = gridInqSize(gridID);
+	  double missval1 = vlistInqVarMissval(vlistID1, varID1);
+	  double missval2 = vlistInqVarMissval(vlistID2, varID2);
 
 	  //checkrel = gridInqType(gridID) != GRID_SPECTRAL;
-          checkrel = TRUE;
+          bool checkrel = true;
 
 	  cdiParamToString(param, paramstr, sizeof(paramstr));
 
 	  streamReadRecord(streamID1, array1, &nmiss1);
 	  streamReadRecord(streamID2, array2, &nmiss2);
 
-	  ndiff = 0;
-          absm = 0.0;
-	  relm = 0.0;
-	  dsgn = FALSE;
-          zero = FALSE;
+	  int ndiff = 0;
+	  bool dsgn = false;
+          bool zero = false;
+          double absm = 0.0;
+	  double relm = 0.0;
+          double absdiff;
 
-	  for ( i = 0; i < gridsize; i++ )
+	  for ( int i = 0; i < gridsize; i++ )
 	    {
 	      if ( (DBL_IS_NAN(array1[i]) && !DBL_IS_NAN(array2[i])) ||
 		  (!DBL_IS_NAN(array1[i]) &&  DBL_IS_NAN(array2[i])) )
@@ -138,9 +130,9 @@ void *Diff(void *argument)
 		  absm = MAX(absm, absdiff);
 
 		  if ( array1[i]*array2[i] < 0. )
-		    dsgn = TRUE;
+		    dsgn = true;
 		  else if ( IS_EQUAL(array1[i]*array2[i], 0.) )
-		    zero = TRUE;
+		    zero = true;
 		  else
 		    relm = MAX(relm, absdiff / MAX(fabs(array1[i]), fabs(array2[i])));
 		}
@@ -158,7 +150,7 @@ void *Diff(void *argument)
 		{
 		  if ( lhead )
 		    {
-		      lhead = FALSE;
+		      lhead = false;
 
 		      set_text_color(stdout, BRIGHT, BLACK);
 		      fprintf(stdout, "               Date     Time   Level Gridsize    Miss ");
diff --git a/src/Distgrid.c b/src/Distgrid.c
index 9e97b83..7ea69a0 100644
--- a/src/Distgrid.c
+++ b/src/Distgrid.c
@@ -42,27 +42,47 @@ void genGrids(int gridID1, int *gridIDs, int nxvals, int nyvals, int nxblocks, i
   int nx = gridInqXsize(gridID1);
   int ny = gridInqYsize(gridID1);
 
+  bool lxcoord = true;
+  bool lycoord = true;
+  if ( gridInqXvals(gridID1, NULL) == 0 ) lxcoord = false;
+  if ( gridInqYvals(gridID1, NULL) == 0 ) lycoord = false;
+
   double *xvals = NULL, *yvals = NULL;
   double *xvals2 = NULL, *yvals2 = NULL;
-  if ( lregular )
+
+  if ( lxcoord )
     {
-      xvals = (double*) Malloc(nx*sizeof(double));
-      yvals = (double*) Malloc(ny*sizeof(double));
+      if ( lregular )
+        {
+          xvals = (double*) Malloc(nx*sizeof(double));
+        }
+      else
+        {
+          xvals = (double*) Malloc(nx*ny*sizeof(double));
+          xvals2 = (double*) Malloc(nxvals*nyvals*sizeof(double));
+        }
+      
+      gridInqXvals(gridID1, xvals);
     }
-  else
+
+  if ( lycoord )
     {
-      xvals = (double*) Malloc(nx*ny*sizeof(double));
-      yvals = (double*) Malloc(nx*ny*sizeof(double));
-      xvals2 = (double*) Malloc(nxvals*nyvals*sizeof(double));
-      yvals2 = (double*) Malloc(nxvals*nyvals*sizeof(double));      
+      if ( lregular )
+        {
+          yvals = (double*) Malloc(ny*sizeof(double));
+        }
+      else
+        {
+          yvals = (double*) Malloc(nx*ny*sizeof(double));
+          yvals2 = (double*) Malloc(nxvals*nyvals*sizeof(double));
+        }
+
+      gridInqYvals(gridID1, yvals);
     }
-  
+ 
   int *xlsize = (int*) Malloc(nxblocks*sizeof(int));
   int *ylsize = (int*) Malloc(nyblocks*sizeof(int));
 
-  gridInqXvals(gridID1, xvals);
-  gridInqYvals(gridID1, yvals);
-
   for ( ix = 0; ix < nxblocks; ++ix ) xlsize[ix] = nxvals;
   if ( nx%nxblocks != 0 ) xlsize[nxblocks-1] = nx - (nxblocks-1)*nxvals;
   if ( cdoVerbose ) for ( ix = 0; ix < nxblocks; ++ix ) cdoPrint("xblock %d: %d", ix, xlsize[ix]);
@@ -89,8 +109,8 @@ void genGrids(int gridID1, int *gridIDs, int nxvals, int nyvals, int nxblocks, i
 	       	// printf(">> %d %d %d\n", j, i, offset + j*nx + i);
                 if ( !lregular )
                   {
-                    xvals2[gridsize2] = xvals[offset + j*nx + i];
-                    yvals2[gridsize2] = yvals[offset + j*nx + i];
+                    if ( lxcoord ) xvals2[gridsize2] = xvals[offset + j*nx + i];
+                    if ( lycoord ) yvals2[gridsize2] = yvals[offset + j*nx + i];
                   }
 		gridindex[index][gridsize2++] = offset + j*nx + i;
 	      }
@@ -103,13 +123,13 @@ void genGrids(int gridID1, int *gridIDs, int nxvals, int nyvals, int nxblocks, i
 
         if ( lregular )
           {
-            gridDefXvals(gridID2, xvals+ix*nxvals);
-            gridDefYvals(gridID2, yvals+iy*nyvals);
+            if ( lxcoord ) gridDefXvals(gridID2, xvals+ix*nxvals);
+            if ( lycoord ) gridDefYvals(gridID2, yvals+iy*nyvals);
           }
         else
           {
-            gridDefXvals(gridID2, xvals2);
-            gridDefYvals(gridID2, yvals2);
+            if ( lxcoord ) gridDefXvals(gridID2, xvals2);
+            if ( lycoord ) gridDefYvals(gridID2, yvals2);
           }
         
 	gridIDs[index] = gridID2;
diff --git a/src/Duplicate.c b/src/Duplicate.c
index 6d7f563..e582de9 100644
--- a/src/Duplicate.c
+++ b/src/Duplicate.c
@@ -26,39 +26,33 @@
 
 void *Duplicate(void *argument)
 {
-  int gridsize;
   int nrecs;
-  int gridID, varID, levelID, recID;
-  int tsID;
-  int nts;
+  int gridID, varID, levelID;
   int nalloc = 0;
-  int streamID1, streamID2;
-  int vlistID1, vlistID2, taxisID1, taxisID2;
   int nmiss;
-  int nvars, nlevel;
-  int ntsteps;
+  int nlevel;
   int *vdate = NULL, *vtime = NULL;
-  int idup, ndup = 2;
+  int ndup = 2;
   field_t ***vars = NULL;
 
   cdoInitialize(argument);
 
-  if ( operatorArgc() > 1 ) cdoAbort("Too many arguments!");
+  if      ( operatorArgc()  > 1 ) cdoAbort("Too many arguments!");
   else if ( operatorArgc() == 1 ) ndup = parameter2int(operatorArgv()[0]);
 
-  if ( cdoVerbose ) cdoPrint("ndup = %d\n", ndup);
+  if ( cdoVerbose ) cdoPrint("ndup = %d", ndup);
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  ntsteps  = vlistNtsteps(vlistID1);
-  nvars    = vlistNvars(vlistID1);
+  int ntsteps  = vlistNtsteps(vlistID1);
+  int nvars    = vlistNvars(vlistID1);
 
   if ( ntsteps == 1 )
     {
@@ -74,13 +68,13 @@ void *Duplicate(void *argument)
 	vlistDefVarTsteptype(vlistID2, varID, TSTEP_INSTANT);
     }
  
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
   nvars = vlistNvars(vlistID1);
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       if ( tsID >= nalloc )
@@ -88,7 +82,7 @@ void *Duplicate(void *argument)
 	  nalloc += NALLOC_INC;
 	  vdate = (int*) Realloc(vdate, nalloc*sizeof(int));
 	  vtime = (int*) Realloc(vtime, nalloc*sizeof(int));
-	  vars  = (field_t ***) Realloc(vars, nalloc*sizeof(field_t **));
+	  vars  = (field_t***) Realloc(vars, nalloc*sizeof(field_t**));
 	}
 
       vdate[tsID] = taxisInqVdate(taxisID1);
@@ -96,11 +90,11 @@ void *Duplicate(void *argument)
 
       vars[tsID] = field_malloc(vlistID1, FIELD_NONE);
 
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  gridID   = vlistInqVarGrid(vlistID1, varID);
-	  gridsize = gridInqSize(gridID);
+	  int gridsize = gridInqSize(gridID);
 	  vars[tsID][varID][levelID].ptr = (double*) Malloc(gridsize*sizeof(double));
 	  streamReadRecord(streamID1, vars[tsID][varID][levelID].ptr, &nmiss);
 	  vars[tsID][varID][levelID].nmiss = nmiss;
@@ -109,9 +103,9 @@ void *Duplicate(void *argument)
       tsID++;
     }
 
-  nts = tsID;
+  int nts = tsID;
 
-  for ( idup = 0; idup < ndup; idup++ )
+  for ( int idup = 0; idup < ndup; idup++ )
     {
       for ( tsID = 0; tsID < nts; tsID++ )
 	{
diff --git a/src/EOFs.c b/src/EOFs.c
index 695949c..6e720f4 100644
--- a/src/EOFs.c
+++ b/src/EOFs.c
@@ -377,7 +377,7 @@ void *EOFs(void * argument)
 	      npack = 0;
 	      for ( i = 0; i < gridsize; ++i )
 		{
-		  if ( !DBL_IS_EQUAL(weight[i], 0) && !DBL_IS_EQUAL(weight[i], missval) &&
+		  if ( !DBL_IS_EQUAL(weight[i], 0.0) && !DBL_IS_EQUAL(weight[i], missval) &&
 		       !DBL_IS_EQUAL(in[i], missval) )
 		    pack[npack++] = i;
 		}
@@ -392,7 +392,7 @@ void *EOFs(void * argument)
 	  ipack = 0;
 	  for ( i = 0; i < gridsize; ++i )
 	    {
-	      if ( !DBL_IS_EQUAL(weight[i], 0) && !DBL_IS_EQUAL(weight[i], missval) &&
+	      if ( !DBL_IS_EQUAL(weight[i], 0.0) && !DBL_IS_EQUAL(weight[i], missval) &&
 		   !DBL_IS_EQUAL(in[i], missval) && pack[ipack++] != i )
 		{
 		  cdoAbort("Missing values unsupported!");
diff --git a/src/EcaIndices.c b/src/EcaIndices.c
index 7ad3975..da9c15c 100755
--- a/src/EcaIndices.c
+++ b/src/EcaIndices.c
@@ -73,16 +73,16 @@
 
 static const char CFD_NAME[]         = "consecutive_frost_days_index_per_time_period";
 static const char CFD_LONGNAME[]     = "Consecutive frost days index is the greatest number of consecutive frost days in a given time period. Frost days is the number of days where minimum of temperature is below 0 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
-static const char CFD_UNITS[]        = "No.";
-static const char CFD_NAME2[]        = "number_of_cfd_periods_with_more_than_5days_per_time_period";
-static const char CFD_LONGNAME2[]    = "Number of cfd periods in given time period with more than 5 days. The time period should be defined by the bounds of the time coordinate.";
+//static const char CFD_UNITS[]        = "No.";
+static const char CFD_NAME2[]        = "number_of_cfd_periods_with_more_than_%ddays_per_time_period";
+static const char CFD_LONGNAME2[]    = "Number of cfd periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
 static const char CFD_UNITS2[]       = "No.";
 
 static const char CSU_NAME[]         = "consecutive_summer_days_index_per_time_period";
 static const char CSU_LONGNAME[]     = "Consecutive summer days index is the greatest number of consecutive summer days in a given time period. Summer days is the number of days where maximum of temperature is above 25 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
-static const char CSU_UNITS[]        = "No.";
-static const char CSU_NAME2[]        = "number_of_csu_periods_with_more_than_5days_per_time_period";
-static const char CSU_LONGNAME2[]    = "Number of csu periods in given time period with more than 5 days. The time period should be defined by the bounds of the time coordinate.";
+//static const char CSU_UNITS[]        = "No.";
+static const char CSU_NAME2[]        = "number_of_csu_periods_with_more_than_%ddays_per_time_period";
+static const char CSU_LONGNAME2[]    = "Number of csu periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
 static const char CSU_UNITS2[]       = "No.";
 
 static const char CWDI_NAME[]        = "cold_wave_duration_index_wrt_mean_of_reference_period";
@@ -101,11 +101,11 @@ static const char CWFI_UNITS2[]      = "No.";
 
 static const char ETR_NAME[]         = "intra_period_extreme_temperature_range";
 static const char ETR_LONGNAME[]     = "Difference between the absolute extreme temperatures in observation period. The time period should be defined by the bounds of the time coordinate.";
-static const char ETR_UNITS[]        = "K";
+//static const char ETR_UNITS[]        = "K";
 
 static const char FD_NAME[]          = "frost_days_index_per_time_period";
 static const char FD_LONGNAME[]      = "Frost days index is the number of days where minimum of temperature is below 0 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
-static const char FD_UNITS[]         = "No.";
+//static const char FD_UNITS[]         = "No.";
 
 static const char GSL_NAME[]         = "thermal_growing_season_length";
 static const char GSL_LONGNAME[]     = "Counted are the number of days per calendar year between the first occurrence of at least %d consecutive days where the daily mean temperature is above %1.0f degree Celsius and the first occurrence of at least %d consecutive days after 1st of July where the daily mean temperature is below %1.0f degree Celsius. The time period should be defined by the bounds of the time coordinate.";
@@ -138,7 +138,7 @@ static const char ID_UNITS[]         = "No.";
 
 static const char SU_NAME[]          = "summer_days_index_per_time_period";
 static const char SU_LONGNAME[]      = "Summer days index is the number of days where maximum of temperature is above %1.0f degree Celsius. The time period should be defined by the bounds of the time coordinate.";
-static const char SU_UNITS[]         = "No.";
+//static const char SU_UNITS[]         = "No.";
 
 static const char TG10P_NAME[]       = "cold_days_percent_wrt_10th_percentile_of_reference_period";
 static const char TG10P_LONGNAME[]   = "This is the percent of time per time period where daily mean temperature is below a reference value. The reference value is calculated  as the 10th percentile of daily mean temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
@@ -171,15 +171,15 @@ static const char TX90P_UNITS[]      = "Percent";
 static const char CDD_NAME[]         = "consecutive_dry_days_index_per_time_period";
 static const char CDD_LONGNAME[]     = "Consecutive dry days is the greatest number of consecutive days per time period with daily precipitation amount  below %g mm. The time period should be defined by the bounds of the time coordinate.";
 static const char CDD_UNITS[]        = "No.";
-static const char CDD_NAME2[]        = "number_of_cdd_periods_with_more_than_5days_per_time_period";
-static const char CDD_LONGNAME2[]    = "Number of cdd periods in given time period with more than 5 days. The time period should be defined by the bounds of the time coordinate.";
+static const char CDD_NAME2[]        = "number_of_cdd_periods_with_more_than_%ddays_per_time_period";
+static const char CDD_LONGNAME2[]    = "Number of cdd periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
 static const char CDD_UNITS2[]       = "No.";
 
 static const char CWD_NAME[]         = "consecutive_wet_days_index_per_time_period";
 static const char CWD_LONGNAME[]     = "Consecutive wet days is the greatest number of consecutive days per time period with daily precipitation above %g mm. The time period should be defined by the bounds of the time coordinate.";
 static const char CWD_UNITS[]        = "No.";
-static const char CWD_NAME2[]        = "number_of_cwd_periods_with_more_than_5days_per_time_period";
-static const char CWD_LONGNAME2[]    = "Number of cwd periods in given time period with more than 5 days. The time period should be defined by the bounds of the time coordinate.";
+static const char CWD_NAME2[]        = "number_of_cwd_periods_with_more_than_%ddays_per_time_period";
+static const char CWD_LONGNAME2[]    = "Number of cwd periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
 static const char CWD_UNITS2[]       = "No.";
 
 static const char PD_NAME[]          = "precipitation_days_index_per_time_period";
@@ -224,7 +224,7 @@ static const char R99P_UNITS[]       = "Percent";
 
 static const char R99PTOT_NAME[]     = "precipitation_percent_due_to_R99p_days";
 static const char R99PTOT_LONGNAME[] = "percentage of  total  precipitation amount per time period  due to  extremely_wet_days_wrt_99th_percentile_of_reference_period. The time period should be defined by the bounds of the time coordinate.";
-static const char R99PTOT_UNITS[]    = "Percent";
+//static const char R99PTOT_UNITS[]    = "Percent";
 
 static const char RR1_NAME[]         = "wet_days_index_per_time_period";
 static const char RR1_LONGNAME[]     = "Wet days index is the number of days per time period with daily precipitation of at least %g mm.  The time period should be defined by the bounds of the time coordinate.";
@@ -241,7 +241,7 @@ static const char RX5DAY_NAME2[]     = "number_of_5day_heavy_precipitation_perio
 static const char RX5DAY_LONGNAME2[] = "Number of 5day periods in given time period with precipitation amount exceeding %1.0f mm / 5 days. The time period should be defined by the bounds of the time coordinate.";
 static const char RX5DAY_UNITS2[]    = "No.";
 
-static const char SDII_NAME[]        = "simple_daily_intensitiy_index_per_time_period";
+static const char SDII_NAME[]        = "simple_daily_intensity_index_per_time_period";
 static const char SDII_LONGNAME[]    = "Simple daily intensity index is the mean of precipitation amount on wet days. A wet day is a day with precipitation sum of at least %g mm. The time period should be defined by the bounds of the time coordinate.";
 static const char SDII_UNITS[]       = "mm";
 
@@ -261,10 +261,10 @@ static const char STRBRE_LONGNAME[]  = "Strong breeze days index is the number o
 static const char STRBRE_NAME2[]     = "consecutive_strong_breeze_days_index_per_time_period";
 static const char STRBRE_LONGNAME2[] = "Greatest number of consecutive strong breeze days per time period. The time period should be defined by the bounds of the time coordinate.";
 
-static const char STRGAL_NAME[]      = "strong_gale_days_index_per_time_period";
-static const char STRGAL_LONGNAME[]  = "Strong gale days index is the number of days per time period where maximum wind speed is above 20.5 m/s. The time period should be defined by the bounds of the time coordinate.";
-static const char STRGAL_NAME2[]     = "consecutive_strong_gale_days_index_per_time_period";
-static const char STRGAL_LONGNAME2[] = "Greatest number of consecutive strong gale days per time period. The time period should be defined by the bounds of the time coordinate.";
+//static const char STRGAL_NAME[]      = "strong_gale_days_index_per_time_period";
+//static const char STRGAL_LONGNAME[]  = "Strong gale days index is the number of days per time period where maximum wind speed is above 20.5 m/s. The time period should be defined by the bounds of the time coordinate.";
+//static const char STRGAL_NAME2[]     = "consecutive_strong_gale_days_index_per_time_period";
+//static const char STRGAL_LONGNAME2[] = "Greatest number of consecutive strong gale days per time period. The time period should be defined by the bounds of the time coordinate.";
 
 static const char HURR_NAME[]        = "hurricane_days_index_per_time_period";
 static const char HURR_LONGNAME[]    = "Hurricane days index is the number of days per time period where maximum wind speed is above 32.5 m/s. The time period should be defined by the bounds of the time coordinate.";
@@ -278,10 +278,22 @@ static const char HURR_LONGNAME2[]   = "Greatest number of consecutive hurricane
 void *EcaCfd(void *argument)
 {
   ECA_REQUEST_1 request;
+  int ndays = 5;
+  char cfd_longname2[1024];
+  char cfd_name2[1024];
   
   cdoInitialize(argument);
   cdoOperatorAdd("eca_cfd", 0, 31, NULL);
   
+  if ( operatorArgc() > 1 ) cdoAbort("Too many arguments!");
+  else if ( operatorArgc() > 0 ) 
+    {
+      ndays = parameter2int(operatorArgv()[0]);
+    }
+
+  sprintf(cfd_longname2, CFD_LONGNAME2, ndays);
+  sprintf(cfd_name2,     CFD_NAME2, ndays);
+
   request.var1.name     = CFD_NAME;
   request.var1.longname = CFD_LONGNAME;
   request.var1.units    = NULL;
@@ -292,11 +304,11 @@ void *EcaCfd(void *argument)
   request.var1.mulc     = 0.0;
   request.var1.addc     = 0.0;
   request.var1.epilog   = NONE;
-  request.var2.name     = CFD_NAME2;
-  request.var2.longname = CFD_LONGNAME2;
+  request.var2.name     = cfd_name2;
+  request.var2.longname = cfd_longname2;
   request.var2.units    = CFD_UNITS2;
   request.var2.h1       = farseleqc;
-  request.var2.h1arg    = 6;
+  request.var2.h1arg    = ndays+1;
   request.var2.h2       = NULL;
   request.var2.h3       = farnum;
    
@@ -309,13 +321,24 @@ void *EcaCfd(void *argument)
 
 void *EcaCsu(void *argument)
 {
-  double argT = 25.0;
   ECA_REQUEST_1 request;
+  double argT = 25.0;
+  int ndays = 5;
+  char csu_longname2[1024];
+  char csu_name2[1024];
   
   cdoInitialize(argument);
   cdoOperatorAdd("eca_csu", 0, 31, NULL);
 
-  if ( operatorArgc() > 0 ) argT = parameter2double(operatorArgv()[0]);
+  if ( operatorArgc() > 2 ) cdoAbort("Too many arguments!");
+  else if ( operatorArgc() > 0 ) 
+    {
+      argT = parameter2double(operatorArgv()[0]);
+      if ( operatorArgc() == 2 ) ndays = parameter2int(operatorArgv()[1]);
+    }
+  
+  sprintf(csu_longname2, CSU_LONGNAME2, ndays);
+  sprintf(csu_name2,     CSU_NAME2, ndays);
 
   request.var1.name     = CSU_NAME;
   request.var1.longname = CSU_LONGNAME;
@@ -327,15 +350,16 @@ void *EcaCsu(void *argument)
   request.var1.mulc     = 0.0;
   request.var1.addc     = 0.0;
   request.var1.epilog   = NONE;
-  request.var2.name     = CSU_NAME2;
-  request.var2.longname = CSU_LONGNAME2;
+  request.var2.name     = csu_name2;
+  request.var2.longname = csu_longname2;
   request.var2.units    = CSU_UNITS2;
   request.var2.h1       = farseleqc;
-  request.var2.h1arg    = 6;
+  request.var2.h1arg    = ndays+1;
   request.var2.h2       = NULL;
   request.var2.h3       = farnum;
   
   eca1(&request);
+  
   cdoFinish();
   
   return 0;
@@ -810,19 +834,19 @@ void *EcaTn90p(void *argument)
 
 void *EcaTr(void *argument)
 {
-  char *longname;
-  double argT = 20.0;
   ECA_REQUEST_1 request;
+  double argT = 20.0;
+  char tr_longname[1024];
   
   cdoInitialize(argument);
   cdoOperatorAdd("eca_tr", 0, 31, NULL);
 
   if ( operatorArgc() > 0 ) argT = parameter2double(operatorArgv()[0]);
-  longname = (char*) Malloc(strlen(TR_LONGNAME) + 40);
-  sprintf(longname, TR_LONGNAME, argT);
+
+  sprintf(tr_longname, TR_LONGNAME, argT);
  
   request.var1.name     = TR_NAME;
-  request.var1.longname = longname;
+  request.var1.longname = tr_longname;
   request.var1.units    = TR_UNITS;
   request.var1.f1       = farselgtc;
   request.var1.f1arg    = TO_KELVIN(argT);
@@ -836,7 +860,6 @@ void *EcaTr(void *argument)
    
   eca1(&request);
   
-  Free(longname);
   cdoFinish();
   
   return 0;
@@ -899,19 +922,28 @@ void *EcaTx90p(void *argument)
 void *EcaCdd(void *argument)
 {
   ECA_REQUEST_1 request;
-  char lnamebuffer[1024];
   double threshold = 1;
+  int ndays = 5;
+  char cdd_longname[1024];
+  char cdd_longname2[1024];
+  char cdd_name2[1024];
   
   cdoInitialize(argument);
   cdoOperatorAdd("eca_cdd", 0, 31, NULL);
 
-  if ( operatorArgc() == 1 ) threshold = parameter2double(operatorArgv()[0]);
-  if ( operatorArgc() > 1 ) cdoAbort("Too many arguments!");
-
-  sprintf(lnamebuffer, CDD_LONGNAME, threshold);
+  if ( operatorArgc() > 2 ) cdoAbort("Too many arguments!");
+  else if ( operatorArgc() > 0 ) 
+    {
+      threshold = parameter2double(operatorArgv()[0]);
+      if ( operatorArgc() == 2 ) ndays = parameter2int(operatorArgv()[1]);
+    }
+  
+  sprintf(cdd_longname,  CDD_LONGNAME, threshold);
+  sprintf(cdd_longname2, CDD_LONGNAME2, ndays);
+  sprintf(cdd_name2,     CDD_NAME2, ndays);
 
   request.var1.name     = CDD_NAME;
-  request.var1.longname = lnamebuffer;
+  request.var1.longname = cdd_longname;
   request.var1.units    = CDD_UNITS;
   request.var1.f1       = farselltc;
   request.var1.f1arg    = threshold;
@@ -920,15 +952,16 @@ void *EcaCdd(void *argument)
   request.var1.mulc     = 0.0;
   request.var1.addc     = 0.0;
   request.var1.epilog   = NONE;
-  request.var2.name     = CDD_NAME2;
-  request.var2.longname = CDD_LONGNAME2;
+  request.var2.name     = cdd_name2;
+  request.var2.longname = cdd_longname2;
   request.var2.units    = CDD_UNITS2;
   request.var2.h1       = farseleqc;
-  request.var2.h1arg    = 6;
+  request.var2.h1arg    = ndays+1;
   request.var2.h2       = NULL;
   request.var2.h3       = farnum;
    
   eca1(&request);
+  
   cdoFinish();
   
   return 0;
@@ -938,19 +971,28 @@ void *EcaCdd(void *argument)
 void *EcaCwd(void *argument)
 {
   ECA_REQUEST_1 request;
-  char lnamebuffer[1024];
   double threshold = 1;
+  int ndays = 5;
+  char cwd_longname[1024];
+  char cwd_longname2[1024];
+  char cwd_name2[1024];
   
   cdoInitialize(argument);
   cdoOperatorAdd("eca_cwd", 0, 31, NULL);
 
-  if ( operatorArgc() == 1 ) threshold = parameter2double(operatorArgv()[0]);
-  if ( operatorArgc() > 1 ) cdoAbort("Too many arguments!");
-
-  sprintf(lnamebuffer, CWD_LONGNAME, threshold);
+  if ( operatorArgc() > 2 ) cdoAbort("Too many arguments!");
+  else if ( operatorArgc() > 0 ) 
+    {
+      threshold = parameter2double(operatorArgv()[0]);
+      if ( operatorArgc() == 2 ) ndays = parameter2int(operatorArgv()[1]);
+    }
+  
+  sprintf(cwd_longname,  CWD_LONGNAME, threshold);
+  sprintf(cwd_longname2, CWD_LONGNAME2, ndays);
+  sprintf(cwd_name2,     CWD_NAME2, ndays);
 
   request.var1.name     = CWD_NAME;
-  request.var1.longname = lnamebuffer;
+  request.var1.longname = cwd_longname;
   request.var1.units    = CWD_UNITS;
   request.var1.f1       = farselgec;
   request.var1.f1arg    = threshold;
@@ -959,15 +1001,16 @@ void *EcaCwd(void *argument)
   request.var1.mulc     = 0.0;
   request.var1.addc     = 0.0;
   request.var1.epilog   = NONE;
-  request.var2.name     = CWD_NAME2;
-  request.var2.longname = CWD_LONGNAME2;
+  request.var2.name     = cwd_name2;
+  request.var2.longname = cwd_longname2;
   request.var2.units    = CWD_UNITS2;
   request.var2.h1       = farseleqc;
-  request.var2.h1arg    = 6;
+  request.var2.h1arg    = ndays+1;
   request.var2.h2       = NULL;
   request.var2.h3       = farnum;
    
   eca1(&request);
+  
   cdoFinish();
   
   return 0;
diff --git a/src/Enlarge.c b/src/Enlarge.c
index e1f5a71..3bfdc45 100644
--- a/src/Enlarge.c
+++ b/src/Enlarge.c
@@ -29,58 +29,55 @@
 
 void *Enlarge(void *argument)
 {
-  int streamID1, streamID2;
-  int vlistID1, vlistID2;
-  int gridID1, gridID2;
-  int i, index, ngrids;
+  int i, index;
   int recID, nrecs;
-  int tsID, varID, levelID;
-  int taxisID1, taxisID2;
+  int varID, levelID;
   int nmiss;
-  int gridsize1, gridsize2;
-  int xsize1, ysize1, xsize2, ysize2;
+  int gridsize1;
+  int gridID1;
+  int xsize1, ysize1;
   int ix, iy;
   int linfo = TRUE;
   double missval;
-  double *array1, *array2;
 
   cdoInitialize(argument);
 
   operatorCheckArgc(1);
 
-  gridID2 = cdoDefineGrid(operatorArgv()[0]);
-  xsize2 = gridInqXsize(gridID2);
-  ysize2 = gridInqYsize(gridID2);
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  int gridID2 = cdoDefineGrid(operatorArgv()[0]);
+  int xsize2 = gridInqXsize(gridID2);
+  int ysize2 = gridInqYsize(gridID2);
 
   if ( cdoVerbose ) fprintf(stderr, "gridID2 %d, xsize2 %d, ysize2 %d\n", gridID2, xsize2, ysize2);
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  gridsize2 = gridInqSize(gridID2);
+  int gridsize2 = gridInqSize(gridID2);
   if ( gridsize2 < vlistGridsizeMax(vlistID1) )
     cdoAbort("Gridsize of input stream is greater than new gridsize!");
 
-  ngrids = vlistNgrids(vlistID1);
+  int ngrids = vlistNgrids(vlistID1);
   for ( index = 0; index < ngrids; index++ )
     {
       vlistChangeGridIndex(vlistID2, index, gridID2);
     }
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  array1 = (double*) Malloc(gridsize2*sizeof(double));
-  array2 = (double*) Malloc(gridsize2*sizeof(double));
+  double *array1 = (double*) Malloc(gridsize2*sizeof(double));
+  double *array2 = (double*) Malloc(gridsize2*sizeof(double));
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Enlargegrid.c b/src/Enlargegrid.c
index 0a0aebe..3d791a6 100644
--- a/src/Enlargegrid.c
+++ b/src/Enlargegrid.c
@@ -170,18 +170,11 @@ void *Enlargegrid(void *argument)
 {
   int varID;
   int nrecs = 0;
-  int tsID, recID, levelID;
-  int streamID1, streamID2;
-  int vlistID1 , vlistID2;
+  int recID, levelID;
   int nmiss1, nmiss2;
-  int gridsize1, gridsize2;
-  int gridID1, gridID2;
-  int taxisID1, taxisID2;
   int index;
-  int i, *gindex = NULL;
-  int ndiffgrids, ngrids;
+  int i;
   double missval1;
-  double *array1, *array2;
 
   cdoInitialize(argument);
 
@@ -189,46 +182,46 @@ void *Enlargegrid(void *argument)
   if ( operatorArgc() < 1 ) cdoAbort("Too few arguments!");
   if ( operatorArgc() > 2 ) cdoAbort("Too many arguments!");
 
-  gridID2 = cdoDefineGrid(operatorArgv()[0]);
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int gridID2 = cdoDefineGrid(operatorArgv()[0]);
 
-  vlistID1 = streamInqVlist(streamID1);
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
 
-  ndiffgrids = 0;
+  int ndiffgrids = 0;
   for ( index = 1; index < vlistNgrids(vlistID1); index++ )
     if ( vlistGrid(vlistID1, 0) != vlistGrid(vlistID1, index) )
       ndiffgrids++;
 
   if ( ndiffgrids > 0 ) cdoAbort("Too many different grids in %s!", cdoStreamName(0)->args);
 
-  gridID1 = vlistGrid(vlistID1, 0);
+  int gridID1 = vlistGrid(vlistID1, 0);
 
-  gridsize1 = gridInqSize(gridID1);
-  gridsize2 = gridInqSize(gridID2);
+  int gridsize1 = gridInqSize(gridID1);
+  int gridsize2 = gridInqSize(gridID2);
 
-  array1 = (double*) Malloc(gridsize1*sizeof(double));
-  array2 = (double*) Malloc(gridsize2*sizeof(double));
-  gindex = (int*) Malloc(gridsize1*sizeof(int));
+  double *array1 = (double*) Malloc(gridsize1*sizeof(double));
+  double *array2 = (double*) Malloc(gridsize2*sizeof(double));
+  int  *gindex = (int*) Malloc(gridsize1*sizeof(int));
 
   gen_index(gridID2, gridID1, gindex);
 
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  ngrids = vlistNgrids(vlistID1);
+  int ngrids = vlistNgrids(vlistID1);
   for ( index = 0; index < ngrids; index++ )
     {
       vlistChangeGridIndex(vlistID2, index, gridID2);
     }
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   vlistDefTaxis(vlistID2, taxisID2);
   streamDefVlist(streamID2, vlistID2);
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Ensstat.c b/src/Ensstat.c
index 7d142d4..39cff41 100644
--- a/src/Ensstat.c
+++ b/src/Ensstat.c
@@ -97,10 +97,8 @@ void *Ensstat(void *argument)
 
   const char *ofilename = cdoStreamName(nfiles)->args;
 
-  if ( !cdoSilentMode && !cdoOverwriteMode )
-    if ( fileExists(ofilename) )
-      if ( !userFileOverwrite(ofilename) )
-	cdoAbort("Outputfile %s already exists!", ofilename);
+  if ( !cdoOverwriteMode && fileExists(ofilename) && !userFileOverwrite(ofilename) )
+    cdoAbort("Outputfile %s already exists!", ofilename);
 
   ens_file_t *ef = (ens_file_t *) Malloc(nfiles*sizeof(ens_file_t));
 
diff --git a/src/Ensstat3.c b/src/Ensstat3.c
index 98328df..134761a 100644
--- a/src/Ensstat3.c
+++ b/src/Ensstat3.c
@@ -111,10 +111,8 @@ void *Ensstat3(void *argument)
 
   ofilename = cdoStreamName(nfiles)->args;
 
-  if ( !cdoSilentMode && !cdoOverwriteMode )
-    if ( fileExists(ofilename) )
-      if ( !userFileOverwrite(ofilename) )
-	cdoAbort("Outputfile %s already exists!", ofilename);
+  if ( !cdoOverwriteMode && fileExists(ofilename) && !userFileOverwrite(ofilename) )
+    cdoAbort("Outputfile %s already exists!", ofilename);
 
   ef = (ens_file_t*) Malloc(nfiles*sizeof(ens_file_t));
 
@@ -225,9 +223,9 @@ void *Ensstat3(void *argument)
 
   if ( operfunc == func_roc ) {
     ctg_tab = (int**) Malloc((nbins+1)*sizeof(int*));
-    hist =    (int*) malloc ( nbins*sizeof(int));
-    uThresh = (double*) Malloc( nbins*sizeof(double));
-    lThresh = (double*) Malloc( nbins*sizeof(double));
+    hist =    (int*) Malloc(nbins*sizeof(int));
+    uThresh = (double*) Malloc(nbins*sizeof(double));
+    lThresh = (double*) Malloc(nbins*sizeof(double));
     roc     = (double**) Malloc((nbins+1)*sizeof(double*));
     
     for  ( i=0; i<nbins; i++ ) {
diff --git a/src/Ensval.c b/src/Ensval.c
index f80c06d..b36bce7 100644
--- a/src/Ensval.c
+++ b/src/Ensval.c
@@ -162,7 +162,7 @@ void *Ensval(void *argument)
   /* check for identical contents of all ensemble members */
   nvars = vlistNvars(ef[0].vlistID);
   if ( cdoVerbose ) 
-    cdoPrint("nvars %i\n",nvars);
+    cdoPrint("nvars %i",nvars);
 
   for ( fileID = 1; fileID < nfiles; fileID++ )
     vlistCompare(ef[0].vlistID, ef[fileID].vlistID, CMP_ALL);
@@ -208,10 +208,8 @@ void *Ensval(void *argument)
     sprintf(ofilename, "%s.%s%s", ofilebase, type_suffix, file_suffix);
     // fprintf(stderr, "StreamID %i: %s\n", stream, ofilename);
 
-    if ( !cdoSilentMode && !cdoOverwriteMode )
-      if ( fileExists(ofilename) )
-	if ( !userFileOverwrite(ofilename) )
-	    cdoAbort("Outputfile %s already exists!", ofilename);
+    if ( !cdoOverwriteMode && fileExists(ofilename) && !userFileOverwrite(ofilename) )
+      cdoAbort("Outputfile %s already exists!", ofilename);
 
     argument_t *fileargument = file_argument_new(ofilename);
     streamID2[stream] = streamOpenWrite(fileargument, cdoFiletype());    
@@ -238,7 +236,7 @@ void *Ensval(void *argument)
   }
 
   if ( cdoVerbose ) 
-    cdoPrint(" sum_weights %10.6f\n",sum_weights);
+    cdoPrint(" sum_weights %10.6f",sum_weights);
   
   tsID = 0;
   do
diff --git a/src/Exprf.c b/src/Exprf.c
index 83ee7b3..545492c 100644
--- a/src/Exprf.c
+++ b/src/Exprf.c
@@ -394,7 +394,7 @@ void *Expr(void *argument)
             {
               int gridID = parse_arg.coords[i].cdiID;
               size_t ngp = parse_arg.coords[i].size;
-              double *data = (double*) malloc(ngp*sizeof(double));
+              double *data = (double*) Malloc(ngp*sizeof(double));
               parse_arg.coords[i].data = data;
               if ( coord == 'x' || coord == 'y' )
                 {
@@ -429,7 +429,7 @@ void *Expr(void *argument)
             {
               int zaxisID = parse_arg.coords[i].cdiID;
               size_t nlev = parse_arg.coords[i].size;
-              double *data = (double*) malloc(nlev*sizeof(double));
+              double *data = (double*) Malloc(nlev*sizeof(double));
               parse_arg.coords[i].data = data;
               zaxisInqLevels(zaxisID, data);
             }
@@ -493,7 +493,9 @@ void *Expr(void *argument)
 
       streamDefTimestep(streamID2, tsID);
 
-      for ( int varID = 0; varID < nvars1; varID++ ) params[varID].nmiss = 0;
+      for ( int varID = 0; varID < nvars1; varID++ )
+        if ( tsID == 0 || params[varID].steptype != TIME_CONSTANT )
+          params[varID].nmiss = 0;
 
       for ( int recID = 0; recID < nrecs; recID++ )
 	{
diff --git a/src/FC.c b/src/FC.c
index ffd30ce..e8cac9f 100644
--- a/src/FC.c
+++ b/src/FC.c
@@ -34,47 +34,40 @@
 
 void *FC(void *argument)
 {
-  int FC2SP, SP2FC, FC2GP, GP2FC;
-  int operatorID;
-  int streamID1, streamID2;
   int nrecs, nvars;
-  int tsID, recID, varID, levelID;
-  int gridsize;
-  int index, ngrids;
-  int vlistID1, vlistID2;
+  int recID, varID, levelID;
+  int index;
   int gridIDsp = -1, gridIDgp = -1, gridIDfc = -1;
   int gridID1 = -1, gridID2 = -1;
   int gridID;
   int nmiss;
   int *vars;
-  int lcopy = FALSE;
-  int taxisID1, taxisID2;
   int nlon = 0, nlat = 0, ntr = 0;
   int nsp = 0, nfc = 0;
-  double *array1 = NULL, *array2 = NULL;
+  double *array2 = NULL;
   SPTRANS *sptrans = NULL;
 
   cdoInitialize(argument);
 
-  FC2SP  = cdoOperatorAdd("fc2sp",  0, 0, NULL);
-  SP2FC  = cdoOperatorAdd("sp2fc", 0, 0, NULL);
-  FC2GP  = cdoOperatorAdd("fc2gp",  0, 0, NULL);
-  GP2FC  = cdoOperatorAdd("gp2fc", 0, 0, NULL);
+  bool lcopy = UNCHANGED_RECORD;
 
-  operatorID = cdoOperatorID();
+  int FC2SP  = cdoOperatorAdd("fc2sp",  0, 0, NULL);
+  int SP2FC  = cdoOperatorAdd("sp2fc", 0, 0, NULL);
+  int FC2GP  = cdoOperatorAdd("fc2gp",  0, 0, NULL);
+  int GP2FC  = cdoOperatorAdd("gp2fc", 0, 0, NULL);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  int operatorID = cdoOperatorID();
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  ngrids = vlistNgrids(vlistID1);
+  int ngrids = vlistNgrids(vlistID1);
   /* find first spectral grid */
   for ( index = 0; index < ngrids; index++ )
     {
@@ -239,12 +232,12 @@ void *FC(void *argument)
 
   if ( gridID1 != -1 ) vlistChangeGrid(vlistID2, gridID1, gridID2);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  gridsize = vlistGridsizeMax(vlistID1);
-  array1 = (double*) Malloc(gridsize*sizeof(double));
+  int gridsize = vlistGridsizeMax(vlistID1);
+  double *array1 = (double*) Malloc(gridsize*sizeof(double));
 
   if ( gridID2 != -1 )
     {
@@ -252,7 +245,7 @@ void *FC(void *argument)
       array2 = (double*) Malloc(gridsize*sizeof(double));
     }
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Filedes.c b/src/Filedes.c
index 393570b..342f4d3 100644
--- a/src/Filedes.c
+++ b/src/Filedes.c
@@ -18,7 +18,7 @@
 /*
    This module contains the following operators:
 
-      Filedes    pardes          Parameter description
+      Filedes    codetab         Parameter code table
       Filedes    griddes         Grid description
       Filedes    vct             Vertical coordinate table
 */
@@ -315,7 +315,6 @@ void filedes(int streamID)
 
 void *Filedes(void *argument)
 {
-  int GRIDDES, GRIDDES2, ZAXISDES, VCT, VCT2, PARDES, FILEDES, VLIST, SPARTAB, PARTAB, PARTAB2;
   int operatorID;
   int streamID = 0;
   int zaxisID;
@@ -325,17 +324,17 @@ void *Filedes(void *argument)
 
   cdoInitialize(argument);
 
-  GRIDDES  = cdoOperatorAdd("griddes",   0, 0, NULL);
-  GRIDDES2 = cdoOperatorAdd("griddes2",  0, 0, NULL);
-  ZAXISDES = cdoOperatorAdd("zaxisdes",  0, 0, NULL);
-  VCT      = cdoOperatorAdd("vct",       0, 0, NULL);
-  VCT2     = cdoOperatorAdd("vct2",      0, 0, NULL);
-  PARDES   = cdoOperatorAdd("pardes",    0, 0, NULL);
-  FILEDES  = cdoOperatorAdd("filedes",   0, 0, NULL);
-  VLIST    = cdoOperatorAdd("vlist",     0, 0, NULL);
-  SPARTAB  = cdoOperatorAdd("spartab",   0, 0, NULL);
-  PARTAB   = cdoOperatorAdd("partab",    0, 0, NULL);
-  PARTAB2  = cdoOperatorAdd("partab2",   0, 0, NULL);
+  int GRIDDES  = cdoOperatorAdd("griddes",   0, 0, NULL);
+  int GRIDDES2 = cdoOperatorAdd("griddes2",  0, 0, NULL);
+  int ZAXISDES = cdoOperatorAdd("zaxisdes",  0, 0, NULL);
+  int VCT      = cdoOperatorAdd("vct",       0, 0, NULL);
+  int VCT2     = cdoOperatorAdd("vct2",      0, 0, NULL);
+  int CODETAB  = cdoOperatorAdd("codetab",   0, 0, NULL);
+  int FILEDES  = cdoOperatorAdd("filedes",   0, 0, NULL);
+  int VLIST    = cdoOperatorAdd("vlist",     0, 0, NULL);
+  int SPARTAB  = cdoOperatorAdd("spartab",   0, 0, NULL);
+  int PARTAB   = cdoOperatorAdd("partab",    0, 0, NULL);
+  int PARTAB2  = cdoOperatorAdd("partab2",   0, 0, NULL);
 
   operatorID = cdoOperatorID();
 
@@ -411,7 +410,7 @@ void *Filedes(void *argument)
     {
       vlistPrint(vlistID);
     }
-  else if ( operatorID == PARDES )
+  else if ( operatorID == CODETAB )
     {
       int varID, code;
       char varname[CDI_MAX_NAME], varlongname[CDI_MAX_NAME], varunits[CDI_MAX_NAME];
diff --git a/src/Fillmiss.c b/src/Fillmiss.c
index 5f1079c..43a9334 100644
--- a/src/Fillmiss.c
+++ b/src/Fillmiss.c
@@ -271,7 +271,7 @@ void fillmiss_one_step(field_t *field1, field_t *field2, int maxfill)
 }
 
 
-void grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr_add, double *restrict nbr_dist, double plon, double plat);
+int grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr_add, double *restrict nbr_dist, double plon, double plat);
 double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_mask, int *restrict nbr_mask, const int *restrict nbr_add, double *restrict nbr_dist);
 unsigned nbr_normalize_weights(unsigned num_neighbors, double dist_tot, const int *restrict nbr_mask, int *restrict nbr_add, double *restrict nbr_dist);
 
@@ -279,6 +279,7 @@ static
 void setmisstodis(field_t *field1, field_t *field2, int num_neighbors)
 {
   int gridID = field1->grid;
+  int gridID0 = gridID;
   double missval = field1->missval;
   double *array1 = field1->ptr;
   double *array2 = field2->ptr;
@@ -400,6 +401,8 @@ void setmisstodis(field_t *field1, field_t *field2, int num_neighbors)
 
   if ( gs ) gridsearch_delete(gs);
 
+  if ( gridID0 != gridID ) gridDestroy(gridID);
+
   if ( lons ) Free(lons);
   if ( lats ) Free(lats);
   Free(xvals);
diff --git a/src/Filter.c b/src/Filter.c
index 9fb56a4..2b4e055 100644
--- a/src/Filter.c
+++ b/src/Filter.c
@@ -51,11 +51,11 @@ void create_fmasc(int nts, double fdata, double fmin, double fmax, int *fmasc)
   double dimin = nts*fmin / fdata;
   double dimax = nts*fmax / fdata;
 
-  int imin = dimin<0 ? 0 : (int)floor(dimin);  
-  int imax = ceil(dimax)>nts/2 ? nts/2 : (int) ceil(dimax);
+  int imin = (dimin < 0) ? 0 : (int)floor(dimin);  
+  int imax = (ceil(dimax) > nts/2) ? nts/2 : (int) ceil(dimax);
 
-  if ( imin < 0 || imin >= nts ) cdoAbort("Parameter fmin=%g out of bounds (1-%d)!", nts);
-  if ( imax < 0 || imax >= nts ) cdoAbort("Parameter fmax=%g out of bounds (1-%d)!", nts);
+  if ( imin < 0 || imin >= nts ) cdoAbort("Parameter fmin=%g: timestep %d out of bounds (1-%d)!", fmin, imin+1, nts);
+  if ( imax < 0 || imax >= nts ) cdoAbort("Parameter fmax=%g: timestep %d out of bounds (1-%d)!", fmax, imax+1, nts);
 
   fmasc[imin] = 1;
   for ( int i = imin+1; i <= imax; i++ )  
@@ -125,12 +125,10 @@ void *Filter(void *argument)
   int gridsize;
   int nrecs;
   int gridID, varID, levelID, recID;
-  int tsID;
-  int nts;
   int nalloc = 0;
   int nmiss;
-  int nvars, nlevel;
-  int incperiod0, incunit0, incunit, calendar;
+  int nlevel;
+  int incperiod0, incunit0, incunit;
   int year0, month0, day0;
   double fdata = 0;
   field_t ***vars = NULL;
@@ -180,11 +178,11 @@ void *Filter(void *argument)
   int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  calendar = taxisInqCalendar(taxisID1);  
+  int calendar = taxisInqCalendar(taxisID1);  
  
-  nvars = vlistNvars(vlistID1);
+  int nvars = vlistNvars(vlistID1);
   
-  tsID = 0;    
+  int tsID = 0;    
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       if ( tsID >= nalloc )
@@ -252,7 +250,7 @@ void *Filter(void *argument)
       tsID++;
     }
   
-  nts = tsID;
+  int nts = tsID;
   if ( nts <= 1 ) cdoAbort("Number of time steps <= 1!");
 
   if ( use_fftw )
@@ -278,8 +276,6 @@ void *Filter(void *argument)
 	}
     }
 
-  int *fmasc = (int*) Calloc(nts, sizeof(int));
-
   switch(operfunc)
     {
     case BANDPASS: 
@@ -310,6 +306,7 @@ void *Filter(void *argument)
 
   if ( cdoVerbose ) cdoPrint("fmin=%g  fmax=%g", fmin, fmax);
   
+  int *fmasc = (int*) Calloc(nts, sizeof(int));
   create_fmasc(nts, fdata, fmin, fmax, fmasc);
 
   for ( varID = 0; varID < nvars; varID++ )
@@ -418,7 +415,7 @@ void *Filter(void *argument)
       field_free(vars[tsID], vlistID1);
     }
 
-  if ( vars   ) Free(vars);
+  if ( vars ) Free(vars);
 
   dtlist_delete(dtlist);
 
diff --git a/src/Gradsdes.c b/src/Gradsdes.c
index e498e67..fce7bdb 100644
--- a/src/Gradsdes.c
+++ b/src/Gradsdes.c
@@ -1393,7 +1393,8 @@ void *Gradsdes(void *argument)
     }
   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);
+      cdoAbort("The fileformat GRIB2 is not fully supported yet for the gradsdes operator.\n"
+               "The .ctl file %s was generated. You can add the necessary .idx file by running\n\tgribmap -i %s", ctlfile, ctlfile);
       // write_map_grib2(idxfile, map_version, nrecords, intnum, fltnum, bignum);
     }
 
@@ -1408,8 +1409,6 @@ void *Gradsdes(void *argument)
   if ( intnum ) Free(intnum);
   if ( fltnum ) Free(fltnum);
 
- END_LABEL:
-
   cdoFinish();
 
   return 0;
diff --git a/src/Harmonic.c b/src/Harmonic.c
index ba3db04..261b724 100644
--- a/src/Harmonic.c
+++ b/src/Harmonic.c
@@ -64,7 +64,7 @@ void *Harmonic(void *argument)
   if ( n_out > 9 ) cdoAbort("Maximum number of wave numbers is 9!");
 
   if ( n < 1 || n < 2 * n_out )
-    cdoAbort("The wave length must be positive and smaller than\n"
+    cdoAbort("The wave length must be positive and smaller than "
 	     "2 times the number of requested harmonics (=%d)!", n_out);
 
   streamID1 = streamOpenRead(cdoStreamName(0));
diff --git a/src/Importcmsaf.c b/src/Importcmsaf.c
index 8fa2b00..50fea96 100644
--- a/src/Importcmsaf.c
+++ b/src/Importcmsaf.c
@@ -1195,7 +1195,7 @@ void read_dataset(hid_t loc_id, const char *name, void *opdata)
 		}
 	      else
 		cdoWarning(" Missing value is inside the range of valid values!\n"
-                           " Dataset %s,  Missval: %g,  Range: %g - %g",
+                           "\tDataset %s,  Missval: %g,  Range: %g - %g",
 			   varname, missval, minval, maxval);
 	    }
 	}
diff --git a/src/Info.c b/src/Info.c
index 3c284f6..e8eb901 100644
--- a/src/Info.c
+++ b/src/Info.c
@@ -247,7 +247,6 @@ void *Info(void *argument)
   int gridsize = 0;
   int gridID, zaxisID;
   int code, param;
-  int vdate, vtime;
   int nrecs;
   int levelID;
   int nmiss;
@@ -275,6 +274,8 @@ void *Info(void *argument)
 
   int operatorID = cdoOperatorID();
 
+  dtlist_type *dtlist = dtlist_new();
+
   for ( int indf = 0; indf < cdoStreamCnt(); indf++ )
     {
       int streamID = streamOpenRead(cdoStreamName(indf));
@@ -293,8 +294,9 @@ void *Info(void *argument)
       int tsID = 0;
       while ( (nrecs = streamInqTimestep(streamID, tsID)) )
 	{
-	  vdate = taxisInqVdate(taxisID);
-	  vtime = taxisInqVtime(taxisID);
+	  dtlist_taxisInqTimestep(dtlist, taxisID, 0);
+	  int vdate = dtlist_get_vdate(dtlist, 0);
+	  int vtime = dtlist_get_vtime(dtlist, 0);
 
 	  date2str(vdate, vdatestr, sizeof(vdatestr));
 	  time2str(vtime, vtimestr, sizeof(vtimestr));
@@ -486,6 +488,8 @@ void *Info(void *argument)
       if ( array ) Free(array);
     }
 
+  dtlist_delete(dtlist);
+
   cdoFinish();
 
   return 0;
diff --git a/src/Input.c b/src/Input.c
index ca6de8a..4f632e0 100644
--- a/src/Input.c
+++ b/src/Input.c
@@ -33,54 +33,32 @@
 static
 int input_iarray(int nval, int *array)
 {
-  int i, n;
   int ival = 0;
 
-  for ( i = 0; i < nval; i++ )
+  for ( int i = 0; i < nval; i++ )
     {
-      n = scanf("%d", &array[i]);
+      int n = scanf("%d", &array[i]);
       if ( n != 1 ) break;
 
       ival++;
     }
 
-  return (ival);
+  return ival;
 }
 
 int input_darray(FILE *gfp, int nval, double *array);
-/*
-static int input_darray(int nval, double *array)
-{
-  int i, n;
-  int ival = 0;
 
-  for ( i = 0; i < nval; i++ )
-    {
-      n = scanf("%lg", &array[i]);
-      if ( n != 1 ) break;
-
-      ival++;
-    }
-
-  return (ival);
-}
-*/
 
 void *Input(void *argument)
 {
   int varID = 0;
-  int nlevs = 1;
   int gridsize0 = 0, gridsize = 0;
-  int gridID = -1, zaxisID, vdate = 0, vtime = 0;
-  int levelID;
   int taxisID = 0;
   int streamID = -1;
   int vlistID = -1;
-  int nmiss = 0;
   int i;
   int code = 0, level = 0, date = 0, time = 0, nlon = 0, nlat = 0;
   int output_filetype = FILETYPE_GRB;
-  int rval;
   int ihead[8];
   double missval = 0;
   double levels[1];
@@ -94,13 +72,21 @@ void *Input(void *argument)
 
   int operatorID = cdoOperatorID();
 
+  int gridID = -1;
+  int zaxisID = -1;
   if ( operatorID == INPUT )
     {
       operatorInputArg("grid description file or name");
-      operatorCheckArgc(1);
+      if ( operatorArgc() == 1 ) operatorCheckArgc(1);
+      else                       operatorCheckArgc(2);
+      
       gridID = cdoDefineGrid(operatorArgv()[0]);
+      if ( operatorArgc() == 2 ) zaxisID = cdoDefineZaxis(operatorArgv()[1]);
     }
 
+  int nlevs = 1;
+  if ( zaxisID != -1 ) nlevs = zaxisInqSize(zaxisID);
+
   levels[0] = 0;
   int nrecs = 0;
 
@@ -116,18 +102,19 @@ void *Input(void *argument)
 	  gridsize = gridInqSize(gridID);
 	  date     = 0;
 	  time     = 0;
+
 	  
 	  if ( nrecs == 0 )
-	    array = (double*) Malloc(gridsize*sizeof(double));
+	    array = (double*) Malloc(gridsize*nlevs*sizeof(double));
 	  
-	  cdoPrint("Enter all %d elements of record %d!", gridsize, nrecs+1);
+	  cdoPrint("Enter all %d elements of timestep %d!", gridsize*nlevs, nrecs+1);
 	  
-	  rval = input_darray(stdin, gridsize, array);
+	  int rval = input_darray(stdin, gridsize*nlevs, array);
 
 	  if ( nrecs > 0 && rval == 0 ) break;
 
-	  if ( rval != gridsize )
-	    cdoAbort("Too few input elements (%d of %d)!", rval, gridsize);
+	  if ( rval != gridsize*nlevs )
+	    cdoAbort("Too few input elements (%d of %d)!", rval, gridsize*nlevs);
 
 	  if ( feof(stdin) ) break;
 	}
@@ -139,7 +126,7 @@ void *Input(void *argument)
 	  cdoPrint("Enter header (code,level,date,time,nlon,nlat,dispo1,dispo2)"
 		   " of record %d (or EOF(=^D))!", nrecs+1);
 
-	  rval = input_iarray(4, ihead);
+	  int rval = input_iarray(4, ihead);
 	  if ( feof(stdin) && nrecs == 0 )
 	    cdoAbort("Too few header elements (%d of %d)!", rval, 4);
 	  if ( feof(stdin) ) break;
@@ -183,7 +170,7 @@ void *Input(void *argument)
 	  cdoPrint("Enter header (code,level,date,time,nlon,nlat,dispo1,dispo2)"
 		   " of record %d (or EOF(=^D))!", nrecs+1);
 
-	  rval = input_iarray(8, ihead);
+	  int rval = input_iarray(8, ihead);
 	  if ( feof(stdin) && nrecs == 0 )
 	    cdoAbort("Too few header elements (%d of %d)!", rval, 8);
 	  if ( feof(stdin) ) break;
@@ -226,8 +213,11 @@ void *Input(void *argument)
 
       if ( nrecs == 0 )
 	{
-	  zaxisID = zaxisCreate(ZAXIS_SURFACE, 1);
-	  zaxisDefLevels(zaxisID, levels);
+          if ( zaxisID == -1 )
+            {
+              zaxisID = zaxisCreate(ZAXIS_SURFACE, 1);
+              zaxisDefLevels(zaxisID, levels);
+            }
 
 	  vlistID = vlistCreate();
 	  varID = vlistDefVar(vlistID, gridID, zaxisID, TSTEP_INSTANT);
@@ -243,21 +233,22 @@ void *Input(void *argument)
 	  streamDefVlist(streamID, vlistID);
 	}
 
-      vdate = date;
-      vtime = time;
+      int vdate = date;
+      int vtime = time;
       taxisDefVdate(taxisID, vdate);
       taxisDefVtime(taxisID, vtime);
       streamDefTimestep(streamID, tsID);
 
-      for ( levelID = 0; levelID < nlevs; levelID++ )
+      for ( int levelID = 0; levelID < nlevs; levelID++ )
 	{
 	  streamDefRecord(streamID, varID, levelID);
 
-	  nmiss = 0;
+          int offset = gridsize*levelID;
+	  int nmiss = 0;
 	  for ( i = 0; i < gridsize; ++i )
-	    if ( DBL_IS_EQUAL(array[i], missval) ) nmiss++;
+	    if ( DBL_IS_EQUAL(array[offset+i], missval) ) nmiss++;
 
-	  streamWriteRecord(streamID, array, nmiss);
+	  streamWriteRecord(streamID, array+offset, nmiss);
 	}
 
       nrecs++;
diff --git a/src/Intgrid.c b/src/Intgrid.c
index 2f82010..ccdfccc 100644
--- a/src/Intgrid.c
+++ b/src/Intgrid.c
@@ -27,6 +27,7 @@
 #include "cdo_int.h"
 #include "pstream.h"
 #include "interpol.h"
+#include "grid.h"
 
 
 int genThinoutGrid(int gridID1, int xinc, int yinc)
@@ -308,33 +309,28 @@ void thinout(field_t *field1, field_t *field2, int xinc, int yinc)
 
 void *Intgrid(void *argument)
 {
-  int INTGRIDBIL, INTGRIDCON, INTPOINT, INTERPOLATE, BOXAVG, THINOUT;
-  int operatorID;
-  int streamID1, streamID2;
-  int nrecs, ngrids;
+  int nrecs;
   int index;
-  int tsID, recID, varID, levelID;
-  int gridsize;
-  int vlistID1, vlistID2;
+  int recID, varID, levelID;
   int gridID1 = -1, gridID2 = -1;
   int nmiss;
   int xinc = 0, yinc = 0;
   double missval;
   double slon, slat;
-  double *array1 = NULL, *array2 = NULL;
   field_t field1, field2;
-  int taxisID1, taxisID2;
 
   cdoInitialize(argument);
 
-  INTGRIDBIL  = cdoOperatorAdd("intgridbil",  0, 0, NULL);
-  INTGRIDCON  = cdoOperatorAdd("intgridcon",  0, 0, NULL);
-  INTPOINT    = cdoOperatorAdd("intpoint",    0, 0, NULL);
-  INTERPOLATE = cdoOperatorAdd("interpolate", 0, 0, NULL);
-  BOXAVG      = cdoOperatorAdd("boxavg",      0, 0, NULL);
-  THINOUT     = cdoOperatorAdd("thinout",     0, 0, NULL);
+  int INTGRIDBIL  = cdoOperatorAdd("intgridbil",  0, 0, NULL);
+  int INTGRIDCON  = cdoOperatorAdd("intgridcon",  0, 0, NULL);
+  int INTPOINT    = cdoOperatorAdd("intpoint",    0, 0, NULL);
+  int INTERPOLATE = cdoOperatorAdd("interpolate", 0, 0, NULL);
+  int BOXAVG      = cdoOperatorAdd("boxavg",      0, 0, NULL);
+  int THINOUT     = cdoOperatorAdd("thinout",     0, 0, NULL);
 
-  operatorID = cdoOperatorID();
+  int operatorID = cdoOperatorID();
+
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
   if ( operatorID == INTGRIDBIL || operatorID == INTGRIDCON || operatorID == INTERPOLATE )
     {
@@ -361,16 +357,14 @@ void *Intgrid(void *argument)
       yinc = parameter2int(operatorArgv()[1]);
     }
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
-
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  ngrids = vlistNgrids(vlistID1);
+  int ngrids = vlistNgrids(vlistID1);
   for ( index = 0; index < ngrids; index++ )
     {
       gridID1 = vlistGrid(vlistID1, index);
@@ -393,7 +387,10 @@ void *Intgrid(void *argument)
 	}
       else
 	{
-	  if ( gridInqType(gridID1) != GRID_LONLAT && gridInqType(gridID1) != GRID_GAUSSIAN )
+          bool ldistgen = false;
+          if ( grid_is_distance_generic(gridID1) && grid_is_distance_generic(gridID2) ) ldistgen = true;
+          
+	  if ( !ldistgen && gridInqType(gridID1) != GRID_LONLAT && gridInqType(gridID1) != GRID_GAUSSIAN )
 	    cdoAbort("Interpolation of %s data unsupported!", gridNamePtr(gridInqType(gridID1)) );
 
 	  if ( gridIsRotated(gridID1) )
@@ -403,20 +400,20 @@ void *Intgrid(void *argument)
       vlistChangeGridIndex(vlistID2, index, gridID2);
     }
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  gridsize = vlistGridsizeMax(vlistID1);
-  array1   = (double*) Malloc(gridsize*sizeof(double));
+  int gridsize = vlistGridsizeMax(vlistID1);
+  double *array1   = (double*) Malloc(gridsize*sizeof(double));
 
   gridsize = gridInqSize(gridID2);
-  array2   = (double*) Malloc(gridsize*sizeof(double));
+  double *array2   = (double*) Malloc(gridsize*sizeof(double));
 
   field_init(&field1);
   field_init(&field2);
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Intlevel.c b/src/Intlevel.c
index 2009e9f..f487648 100644
--- a/src/Intlevel.c
+++ b/src/Intlevel.c
@@ -94,11 +94,11 @@ static
 void vert_gen_weights(int expol, int nlev1, double *lev1, int nlev2, double *lev2,
 		      int *lev_idx1, int *lev_idx2, double *lev_wgt1, double *lev_wgt2)
 {
-  int i1, i2;
+  int i1;
   int    idx1 = 0, idx2 = 0;
   double val1, val2 = 0;
 
-  for ( i2 = 0; i2 < nlev2; ++i2 )
+  for ( int i2 = 0; i2 < nlev2; ++i2 )
     {
       for ( i1 = 1; i1 < nlev1; ++i1 )
 	{
@@ -165,24 +165,13 @@ void *Intlevel(void *argument)
   int gridsize;
   int recID, nrecs;
   int i, offset;
-  int tsID, varID, levelID;
-  int nvars;
+  int varID, levelID;
   int nmiss;
-  int zaxisID1 = -1, zaxisID2;
+  int zaxisID1 = -1;
   int gridID, zaxisID;
-  int nlev1, nlev2, nlevel = 0, maxlev;
-  int lup, ldown;
-  int **varnmiss = NULL;
-  int *varinterp = NULL;
-  int *vars = NULL;
-  int expol = FALSE;
+  int nlevel = 0;
   double missval;
-  double *lev1 = NULL, *lev2 = NULL;
   double *single1, *single2;
-  double **vardata1 = NULL, **vardata2 = NULL;
-  int *lev_idx1, *lev_idx2;
-  double *lev_wgt1, *lev_wgt2;
-  LIST *flist = listNew(FLT_LIST);
 
   cdoInitialize(argument);
 
@@ -193,12 +182,14 @@ void *Intlevel(void *argument)
 
   int operatorID = cdoOperatorID();
 
-  if ( operatorID == INTLEVELX ) expol = TRUE;
+  bool expol = false;
+  if ( operatorID == INTLEVELX ) expol = true;
 
   operatorInputArg("levels");
 
-  nlev2 = args2fltlist(operatorArgc(), operatorArgv(), flist);
-  lev2  = (double *) listArrayPtr(flist);
+  LIST *flist = listNew(FLT_LIST);
+  int nlev2 = args2fltlist(operatorArgc(), operatorArgv(), flist);
+  double *lev2  = (double *) listArrayPtr(flist);
 
   if ( cdoVerbose ) for ( i = 0; i < nlev2; ++i ) printf("lev2 %d: %g\n", i, lev2[i]);
 
@@ -226,30 +217,30 @@ void *Intlevel(void *argument)
 
   if ( i == nzaxis ) cdoAbort("No processable variable found!");
 
-  nlev1 = nlevel;
-  lev1  = (double*) Malloc((nlev1+2)*sizeof(double));
+  int nlev1 = nlevel;
+  double *lev1 = (double*) Malloc((nlev1+2)*sizeof(double));
   zaxisInqLevels(zaxisID1, lev1+1);
 
-  lup = FALSE;
-  ldown = FALSE;
+  bool lup = false;
+  bool ldown = false;
   for ( i = 1; i < nlev1; ++i )
     {
       if ( i == 1 )
 	{
 	  if ( lev1[i+1] > lev1[i] )
-	    lup = TRUE;
+	    lup = true;
 	  else if ( lev1[i+1] < lev1[i] )
-	    ldown = TRUE;	
+	    ldown = true;	
 	}
       else
 	{
 	  if ( lup )
 	    {
-	      if ( !(lev1[i+1] > lev1[i]) ) lup = FALSE;
+	      if ( !(lev1[i+1] > lev1[i]) ) lup = false;
 	    }
 	  else if ( ldown )
 	    {
-	      if ( !(lev1[i+1] < lev1[i]) ) ldown = FALSE;
+	      if ( !(lev1[i+1] < lev1[i]) ) ldown = false;
 	    }
 	}
     }
@@ -269,14 +260,14 @@ void *Intlevel(void *argument)
 
   if ( cdoVerbose ) for ( i = 0; i < nlev1+2; ++i ) printf("lev1 %d: %g\n", i, lev1[i]);
 
-  lev_idx1 = (int*) Malloc(nlev2*sizeof(int));
-  lev_idx2 = (int*) Malloc(nlev2*sizeof(int));
-  lev_wgt1 = (double*) Malloc(nlev2*sizeof(double));
-  lev_wgt2 = (double*) Malloc(nlev2*sizeof(double));
+  int *lev_idx1 = (int*) Malloc(nlev2*sizeof(int));
+  int *lev_idx2 = (int*) Malloc(nlev2*sizeof(int));
+  double *lev_wgt1 = (double*) Malloc(nlev2*sizeof(double));
+  double *lev_wgt2 = (double*) Malloc(nlev2*sizeof(double));
 
   vert_gen_weights(expol, nlev1+2, lev1, nlev2, lev2, lev_idx1, lev_idx2, lev_wgt1, lev_wgt2);
 
-  zaxisID2 = zaxisCreate(zaxisInqType(zaxisID1), nlev2);
+  int zaxisID2 = zaxisCreate(zaxisInqType(zaxisID1), nlev2);
   zaxisDefLevels(zaxisID2, lev2);
   {
     char str[256];
@@ -301,15 +292,15 @@ void *Intlevel(void *argument)
 
   streamDefVlist(streamID2, vlistID2);
 
-  nvars = vlistNvars(vlistID1);
+  int nvars = vlistNvars(vlistID1);
 
-  vars      = (int*) Malloc(nvars*sizeof(int));
-  vardata1  = (double**) Malloc(nvars*sizeof(double*));
-  vardata2  = (double**) Malloc(nvars*sizeof(double*));
-  varnmiss  = (int**) Malloc(nvars*sizeof(int*));
-  varinterp = (int*) Malloc(nvars*sizeof(int));
+  bool *vars = (bool*) Malloc(nvars*sizeof(bool));
+  bool *varinterp = (bool*) Malloc(nvars*sizeof(bool));
+  int **varnmiss = (int**) Malloc(nvars*sizeof(int*));
+  double **vardata1 = (double**) Malloc(nvars*sizeof(double*));
+  double **vardata2 = (double**) Malloc(nvars*sizeof(double*));
 
-  maxlev   = nlev1 > nlev2 ? nlev1 : nlev2;
+  int maxlev = nlev1 > nlev2 ? nlev1 : nlev2;
 
   for ( varID = 0; varID < nvars; varID++ )
     {
@@ -322,24 +313,24 @@ void *Intlevel(void *argument)
 
       if ( zaxisID == zaxisID1 )
 	{
-	  varinterp[varID] = TRUE;
+	  varinterp[varID] = true;
 	  vardata2[varID]  = (double*) Malloc(gridsize*nlev2*sizeof(double));
 	  varnmiss[varID]  = (int*) Malloc(maxlev*sizeof(int));
 	  memset(varnmiss[varID], 0, maxlev*sizeof(int));
 	}
       else
 	{
-	  varinterp[varID] = FALSE;
+	  varinterp[varID] = false;
 	  vardata2[varID]  = vardata1[varID];
 	  varnmiss[varID]  = (int*) Malloc(nlevel*sizeof(int));
 	}
     }
 
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
-      for ( varID = 0; varID < nvars; ++varID ) vars[varID] = FALSE;
+      for ( varID = 0; varID < nvars; ++varID ) vars[varID] = false;
 
       taxisCopyTimestep(taxisID2, taxisID1);
 
@@ -353,7 +344,7 @@ void *Intlevel(void *argument)
 	  single1  = vardata1[varID] + offset;
 	  
 	  streamReadRecord(streamID1, single1, &varnmiss[varID][levelID]);
-	  vars[varID] = TRUE;
+	  vars[varID] = true;
 	}
 
       for ( varID = 0; varID < nvars; varID++ )
@@ -420,7 +411,7 @@ void *Intlevel(void *argument)
   Free(lev_wgt1);
   Free(lev_wgt2);
 
-  if (lev1) Free(lev1);
+  Free(lev1);
 
   listDelete(flist);
 
diff --git a/src/Intlevel3d.c b/src/Intlevel3d.c
index 73033a6..372529b 100644
--- a/src/Intlevel3d.c
+++ b/src/Intlevel3d.c
@@ -49,18 +49,10 @@ void *Intlevel3d(void *argument)
   int zaxisID1 = -1, zaxisID3;
   int gridID3 = -1, gridID, zaxisID;
   int nlevi, nlevo, nlevel = 0, maxlev;
-  int lup, ldown;
-  int **varnmiss = NULL;
-  int *varinterp = NULL;
-  int *vars = NULL;
-  int expol = FALSE;
   double missval;
   double *lev1 = NULL, *lev2 = NULL;
   double *single1, *single2;
-  double **vardata1 = NULL, **vardata2 = NULL;
   int taxisID1, taxisID3;
-  int *lev_idx1, *lev_idx2;
-  double *lev_wgt1, *lev_wgt2;
   double *zlevels_in, *zlevels_out;
   int zlevels_in_miss, zlevels_out_miss;
   char varname[10]; 
@@ -72,20 +64,22 @@ void *Intlevel3d(void *argument)
 
   int operatorID = cdoOperatorID();
 
-  if      ( operatorID == INTLEVEL3D )  expol = FALSE;
-  else if ( operatorID == INTLEVELX3D ) expol = TRUE;
+  bool expol = false;
+  if      ( operatorID == INTLEVEL3D )  expol = false;
+  else if ( operatorID == INTLEVELX3D ) expol = true;
 
   operatorInputArg("icoordinate");
 
+  int streamID1 = streamOpenRead(cdoStreamName(0));                 /*  input data */
+  int streamID2 = streamOpenRead(cdoStreamName(1));                 /*  3d target vertical coordinate */
+  int streamID3 = streamOpenWrite(cdoStreamName(2),cdoFiletype());  /*  output stream */
+
   /*  Read filename from Parameter */
   operatorInputArg("filename for vertical source coordinates variable");
   operatorCheckArgc(1);
   argument_t *fileargument = file_argument_new(operatorArgv()[0]);
   int streamID0 = streamOpenRead(fileargument);                     /*  3d vertical input coordinate */
   file_argument_free(fileargument);
-  int streamID1 = streamOpenRead(cdoStreamName(0));                 /*  input data */
-  int streamID2 = streamOpenRead(cdoStreamName(1));                 /*  3d target vertical coordinate */
-  int streamID3 = streamOpenWrite(cdoStreamName(2),cdoFiletype());  /*  output stream */
 
   int vlistID0 = streamInqVlist(streamID0);
   int vlistID1 = streamInqVlist(streamID1); taxisID1 = vlistInqTaxis(vlistID1);
@@ -99,7 +93,7 @@ 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);
@@ -118,7 +112,7 @@ 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);
+    if (cdoVerbose) cdoPrint("%d records input 3d vertical height",nrecs);
 
     for ( recID = 0; recID < nrecs; recID++ )
       {
@@ -154,7 +148,7 @@ 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",nrecs,gridsize);
 
     for ( recID = 0; recID < nrecs; recID++ )
       {
@@ -168,7 +162,7 @@ void *Intlevel3d(void *argument)
 
   /* Missing values are not allowed for coordinate variables */
   if ( 0 != zlevels_in_miss  )
-    cdoAbort("Input vertical coordinate variables are not allowd to contain missing values.");
+    cdoAbort("Input vertical coordinate variables are not allowed to contain missing values.");
   else
     {
       if ( cdoVerbose ) cdoPrint("Input vertical coordinate has no missing values.");
@@ -187,7 +181,7 @@ void *Intlevel3d(void *argument)
    * (later use of gridsizeo ONLY)
    */
   if ( gridsizei != gridsizeo )
-    cdoAbort("Input and output vertical coordinate must have the same gridsize");
+    cdoAbort("Input and output vertical coordinate must have the same gridsize!");
 
   gridSize = gridsizeo;
 
@@ -206,43 +200,52 @@ void *Intlevel3d(void *argument)
    * number of levels as the input vertical levels from operators parameter
    * (streamID0). Variables with a different z-axis should be copied into output.
    */
-  nzaxis  = vlistNzaxis(vlistID1);
-  for ( i = 0; i < nzaxis; i++ )
-  {
-    zaxisID = vlistZaxis(vlistID1, i);
-    nlevel  = zaxisInqSize(zaxisID);
-    if ( nlevel == nlevi )
+  nzaxis = vlistNzaxis(vlistID1);
+  for ( i = 0; i < nzaxis; ++i )
     {
-      zaxisID1 = zaxisID;
-      break;
+      zaxisID = vlistZaxis(vlistID1, i);
+      nlevel  = zaxisInqSize(zaxisID);
+      if ( nlevel == nlevi )
+        {
+          zaxisID1 = zaxisID;
+          break;
+        }
     }
-  }
-  if ( i == nzaxis ) cdoAbort("No processable variable found!");
+  if ( i == nzaxis ) cdoAbort("No processable variable found (vertical coordinate differ)!");
 
+  int ngrids = vlistNgrids(vlistID1);
+  for ( i = 0; i < ngrids; ++i )
+    {
+      gridID = vlistGrid(vlistID1, i);
+      gridsize = gridInqSize(gridID);
+      if ( gridsize == gridSize ) break;
+    }
+  if ( i == nzaxis ) cdoAbort("No processable variable found (grid coordinate differ)!");
+  
   /*
    * Check monotony of vertical levels
    */
-  lup = FALSE;
-  ldown = FALSE;
+  bool lup = false;
+  bool ldown = false;
   lev1 = zlevels_in + gridSize;
   for ( i = 0; i < nlevi-1; i++ )
     {
       if ( i == 1 )
 	{
 	  if ( lev1[(i+1)*gridSize] > lev1[i*gridSize] )
-	    lup = TRUE;
+	    lup = true;
 	  else if ( lev1[(i+1)*gridSize] < lev1[i*gridSize] )
-	    ldown = TRUE;	
+	    ldown = true;	
 	}
       else
 	{
 	  if ( lup )
 	    {
-	      if ( !(lev1[(i+1)*gridSize] > lev1[i*gridSize]) ) lup = FALSE;
+	      if ( !(lev1[(i+1)*gridSize] > lev1[i*gridSize]) ) lup = false;
 	    }
 	  else if ( ldown )
 	    {
-	      if ( !(lev1[(i+1)*gridSize] < lev1[i*gridSize]) ) ldown = FALSE;
+	      if ( !(lev1[(i+1)*gridSize] < lev1[i*gridSize]) ) ldown = false;
 	    }
 	}
     }
@@ -270,10 +273,10 @@ void *Intlevel3d(void *argument)
   /*
    * Create weights for later interpolation - assumption: input vertical correct is constant in time
    */
-  lev_idx1 = (int*) Malloc(nlevo*gridSize*sizeof(int));
-  lev_idx2 = (int*) Malloc(nlevo*gridSize*sizeof(int));
-  lev_wgt1 = (double*) Malloc(nlevo*gridSize*sizeof(double));
-  lev_wgt2 = (double*) Malloc(nlevo*gridSize*sizeof(double));
+  int *lev_idx1 = (int*) Malloc(nlevo*gridSize*sizeof(int));
+  int *lev_idx2 = (int*) Malloc(nlevo*gridSize*sizeof(int));
+  double *lev_wgt1 = (double*) Malloc(nlevo*gridSize*sizeof(double));
+  double *lev_wgt2 = (double*) Malloc(nlevo*gridSize*sizeof(double));
 
   vert_gen_weights3d(expol, nlevi+2, gridSize, zlevels_in, nlevo, zlevels_out, lev_idx1, lev_idx2, lev_wgt1, lev_wgt2);
 
@@ -313,15 +316,14 @@ void *Intlevel3d(void *argument)
 
   maxlev    = nlevi > nlevo ? nlevi : nlevo;
   nvars     = vlistNvars(vlistID1);
-  vars      = (int*) Malloc(nvars*sizeof(int));
-  vardata1  = (double**) Malloc(nvars*sizeof(double*)); /* input                                         */
-  vardata2  = (double**) Malloc(nvars*sizeof(double*)); /* output                                        */
-  varnmiss  = (int**) Malloc(nvars*sizeof(int*));    /* can for missing values of arbitrary variables */
-  varinterp = (int*) Malloc(nvars*sizeof(int));     /* marker for variables to be interpolated       */
+  bool *vars = (bool*) Malloc(nvars*sizeof(bool));
+  bool *varinterp = (bool*) Malloc(nvars*sizeof(bool));   /* marker for variables to be interpolated       */
+  int **varnmiss = (int**) Malloc(nvars*sizeof(int*));    /* can for missing values of arbitrary variables */
+  double **vardata1 = (double**) Malloc(nvars*sizeof(double*)); /* input                                         */
+  double **vardata2 = (double**) Malloc(nvars*sizeof(double*)); /* output                                        */
 
   /* by default no variable should be interpolated */
-  for ( i = 0; i < nvars; i++ )
-    varinterp[varID] = FALSE;
+  for ( i = 0; i < nvars; i++ ) varinterp[varID] = false;
 
   for ( varID = 0; varID < nvars; varID++ )
     {
@@ -354,14 +356,14 @@ void *Intlevel3d(void *argument)
                memcmp(lonIn,lonOut,nlonIn*sizeof(double)) ||
                memcmp(latIn,latOut,nlatIn*sizeof(double))*/ )
             {
-              varinterp[varID] = FALSE;
+              varinterp[varID] = false;
               vardata2[varID]  = vardata1[varID];
               varnmiss[varID]  = (int*) Malloc(nlevel*sizeof(int));
-              if ( cdoVerbose ) cdoPrint("Ignore variable %s with %d levels\n",varname,nlevel);
+              if ( cdoVerbose ) cdoPrint("Ignore variable %s with %d levels",varname,nlevel);
             }
           else
             {
-              varinterp[varID] = TRUE;
+              varinterp[varID] = true;
               vardata2[varID]  = (double*) Malloc(gridsize*nlevo*sizeof(double));
               varnmiss[varID]  = (int*) Malloc(maxlev*sizeof(int));
               memset(varnmiss[varID], 0, maxlev*sizeof(int));
@@ -369,17 +371,23 @@ void *Intlevel3d(void *argument)
         }
       else
         {
-          varinterp[varID] = FALSE;
+          varinterp[varID] = false;
           vardata2[varID]  = vardata1[varID];
           varnmiss[varID]  = (int*) Malloc(nlevel*sizeof(int));
-          if ( cdoVerbose ) cdoPrint("Ignore variable %s with %d levels\n",varname,nlevel);
+          if ( cdoVerbose ) cdoPrint("Ignore variable %s with %d levels",varname,nlevel);
         }
-      }
+    }
+
+  for ( varID = 0; varID < nvars; varID++ )
+    {
+      if ( varinterp[varID] ) break;
+    }
+  if ( varID == nvars ) cdoAbort("No processable variable found!");
 
   tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
-      for ( varID = 0; varID < nvars; ++varID ) vars[varID] = FALSE;
+      for ( varID = 0; varID < nvars; ++varID ) vars[varID] = false;
 
       taxisCopyTimestep(taxisID3, taxisID1);
 
@@ -397,7 +405,7 @@ void *Intlevel3d(void *argument)
 	  offset   = gridsize*levelID;
 	  single1  = vardata1[varID] + offset;
           streamReadRecord(streamID1, single1, &varnmiss[varID][levelID]);
-	  vars[varID] = TRUE;
+	  vars[varID] = true;
 	}
 
       /* Perform the interpolation on all valid data variables */
@@ -463,7 +471,7 @@ void *Intlevel3d(void *argument)
       tsID++;
     }
 
-  nvars     = vlistNvars(vlistID1);
+  nvars = vlistNvars(vlistID1);
   for ( varID = 0; varID < nvars; varID++ )
     {
       Free(varnmiss[varID]);
diff --git a/src/Invertlev.c b/src/Invertlev.c
index 8183c61..fd3310a 100644
--- a/src/Invertlev.c
+++ b/src/Invertlev.c
@@ -90,12 +90,11 @@ void *Invertlev(void *argument)
   int nmiss;
   int nlev, nlevel;
   int gridID, zaxisID, offset;
-  int lcopy = FALSE;
-  int linvert = FALSE;
+  bool linvert = false;
 
   cdoInitialize(argument);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
   cdoOperatorAdd("invertlev", func_all, 0, NULL);
 
@@ -140,13 +139,13 @@ void *Invertlev(void *argument)
 	}
       else
 	{
-	  linvert = TRUE;
+	  linvert = true;
 	  vardata[varID]  = (double*) Malloc(gridsize*nlev*sizeof(double));
 	  varnmiss[varID] = (int*) Malloc(nlev*sizeof(int));
 	}
     }
 
-  if ( linvert == FALSE ) cdoWarning("No variables with invertable levels found!");
+  if ( linvert == false ) cdoWarning("No variables with invertable levels found!");
 
   int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
diff --git a/src/Isosurface.c b/src/Isosurface.c
index 0181d01..1b13e71 100644
--- a/src/Isosurface.c
+++ b/src/Isosurface.c
@@ -107,7 +107,7 @@ void *Isosurface(void *argument)
 
   isoval = parameter2double(operatorArgv()[0]);
 
-  if ( cdoVerbose ) cdoPrint("Isoval: %g\n", isoval);
+  if ( cdoVerbose ) cdoPrint("Isoval: %g", isoval);
 
 
   streamID1 = streamOpenRead(cdoStreamName(0));
diff --git a/src/Kvl.c b/src/Kvl.c
index f8bb495..5d1a9a5 100644
--- a/src/Kvl.c
+++ b/src/Kvl.c
@@ -171,7 +171,7 @@ void *Kvl(void *argument)
       if ( operatorArgc() != 1 ) cdoAbort("Too few arguments!");
       filename = operatorArgv()[0];
 
-      if ( cdoVerbose ) cdoPrint("Parse file: %s\n", filename);
+      if ( cdoVerbose ) cdoPrint("Parse file: %s", filename);
 
       read_cmor_table(filename);
     }
@@ -180,7 +180,7 @@ void *Kvl(void *argument)
       if ( operatorArgc() != 1 ) cdoAbort("Too few arguments!");
       filename = operatorArgv()[0];
 
-      if ( cdoVerbose ) cdoPrint("Parse file: %s\n", filename);
+      if ( cdoVerbose ) cdoPrint("Parse file: %s", filename);
 
       conv_cmor_table(filename);
     }
@@ -189,7 +189,7 @@ void *Kvl(void *argument)
       if ( operatorArgc() != 1 ) cdoAbort("Too few arguments!");
       filename = operatorArgv()[0];
 
-      if ( cdoVerbose ) cdoPrint("Parse file: %s\n", filename);
+      if ( cdoVerbose ) cdoPrint("Parse file: %s", filename);
 
       // conv_partab(filename);
     }
diff --git a/src/Maggraph.c b/src/Maggraph.c
index 4effca3..4110e7d 100644
--- a/src/Maggraph.c
+++ b/src/Maggraph.c
@@ -970,7 +970,7 @@ void *Maggraph(void *argument)
 
           double val;
 	  streamInqRecord( streamID, &varID, &levelID );
-	  streamReadRecord( streamID, &val, &nmiss );	
+	  streamReadRecord( streamID, &val, &nmiss );
 	  datatab[ fileID ][ tsID ] = val;
 	  vdate[ fileID ][ tsID ] = taxisInqVdate(taxisID);
 	  vtime[ fileID ][ tsID ] = taxisInqVtime(taxisID);
diff --git a/src/Magplot.c b/src/Magplot.c
index 085c9b9..54bdd55 100644
--- a/src/Magplot.c
+++ b/src/Magplot.c
@@ -952,7 +952,7 @@ int ReadColourTable( char *filepath )
     
   if ( !num_colors )
     {
-      cdoWarning("No colours found in File, proceeding with Standard Colour table!\n");
+      cdoWarning("No colours found in File, proceeding with Standard Colour table!");
       fclose(fp);
       return 1;
     }
@@ -996,11 +996,11 @@ int ReadColourTable( char *filepath )
     
   if( USR_COLOUR_COUNT < num_colors )
     {
-      cdoWarning( " Discarding improper format colours and continuing!\n" );
+      cdoWarning( " Discarding improper format colours and continuing!" );
     }
 
-  for ( i = 0; i < num_colors; i++ ) free(temp_table[i]);
-  free(temp_table);
+  for ( i = 0; i < num_colors; i++ ) Free(temp_table[i]);
+  Free(temp_table);
     
   return 0;
 }
@@ -1024,7 +1024,7 @@ int checkstyle( char *style_in )
       }
       
     if( !found )
-	 cdoWarning( " Style specified with Improper value!\n" );
+	 cdoWarning( " Style specified with Improper value!" );
     
     return 1; 
 }
@@ -1057,7 +1057,7 @@ int checkdevice( char *device_in )
       }
       
     if( !found )
-	 cdoWarning( " Device specified with Improper value!\n" );
+	 cdoWarning( " Device specified with Improper value!" );
     
     return 1; 
 }
@@ -1084,9 +1084,9 @@ int checkprojection( char *projection_in )
       
     if( !found )
       {	
-	 cdoWarning( " Projection specified with Improper value!\n" );
-	 cdoWarning( " Specify one of the following:\n" );
-	 cdoWarning( " cylindrical polar_stereographic polar_north geos meteosat meteosat_57E geos_east lambert EPSG3857 goode collignon mollweide robinson bonne google efas EPSG4326 lambert_north_atlantic mercator cartesian taylor tephigram\n" );
+	 cdoWarning( " Projection specified with Improper value!" );
+	 cdoWarning( " Specify one of the following:" );
+	 cdoWarning( " cylindrical polar_stereographic polar_north geos meteosat meteosat_57E geos_east lambert EPSG3857 goode collignon mollweide robinson bonne google efas EPSG4326 lambert_north_atlantic mercator cartesian taylor tephigram" );
 
       }	
     
@@ -1135,7 +1135,6 @@ void *Magplot(void *argument)
   int varID = 0;
   int gridID  = vlistInqVarGrid(vlistID, varID);
   // int zaxisID = vlistInqVarZaxis(vlistID, varID);
-  // double missval = vlistInqVarMissval(vlistID, varID);
 
   int gridtype = gridInqType(gridID);
   if ( gridtype == GRID_GME          ) cdoAbort("GME grid unspported!");
@@ -1181,7 +1180,7 @@ void *Magplot(void *argument)
         {
       	  if( nrecs > 1 )
 	    {
-	      cdoWarning("File has more than one variable! Animation creation not possible!!! \n");
+	      cdoWarning("File has more than one variable! Animation creation not possible!!!");
 	      break;
             }
       	  if( tsID % STEP_FREQ )
@@ -1197,7 +1196,7 @@ void *Magplot(void *argument)
           	if( tsID % STEP_FREQ )
 	    	  {
                      tsID++;
-	             cdoWarning("NOT PLOTTING STEP %d!!!\n",tsID);
+	             cdoWarning("NOT PLOTTING STEP %d!!!",tsID);
 	             continue;
 	    	  }
             }
@@ -1226,6 +1225,9 @@ void *Magplot(void *argument)
 	{
 	  streamInqRecord(streamID, &varID, &levelID);
 	  streamReadRecord(streamID, array, &nmiss);
+
+          if ( nmiss ) cdoSetNAN(vlistInqVarMissval(vlistID, varID), gridsize, array);
+	  
 	  vlistInqVarName(vlistID, varID, varname);
 	  vlistInqVarUnits(vlistID, varID, units);
 
diff --git a/src/Magvector.c b/src/Magvector.c
index 9c29ecd..a122ae1 100644
--- a/src/Magvector.c
+++ b/src/Magvector.c
@@ -349,7 +349,6 @@ void *Magvector(void *argument)
   int varID = 0;
   int gridID  = vlistInqVarGrid(vlistID, varID);
   // int zaxisID = vlistInqVarZaxis(vlistID, varID);
-  // double missval = vlistInqVarMissval(vlistID, varID);
 
   if ( gridInqType(gridID) == GRID_GME          ) cdoAbort("GME grid unspported!");
   if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) cdoAbort("Unstructured grid unspported!");
@@ -423,17 +422,17 @@ void *Magvector(void *argument)
 	    {
 	       if( !strcmp( varname, "var131" ) || !strcmp( varname, "u" ) ) /* U Velocity as per GRIB is 'var131, as per NC 'u' */
 	  	 {
-                      if( DBG )
-          		fprintf( stderr,"Found U VEL in Varname %s\n",varname );
-		      streamReadRecord(streamID, uarray, &nmiss);
-		      found ++;
+                   if( DBG ) fprintf( stderr,"Found U VEL in Varname %s\n",varname );
+                   streamReadRecord(streamID, uarray, &nmiss);
+                   if ( nmiss ) cdoSetNAN(vlistInqVarMissval(vlistID, varID), gridsize, uarray);
+                   found++;
 	  	 }
 	       if( !strcmp( varname, "var132" ) || !strcmp( varname, "v" ) ) /* V Velocity as per GRIB  is 'var132, as per NC 'v'*/
 	  	 {
-                      if( DBG )
-          		fprintf( stderr,"Found V VEL in Varname %s\n",varname );
-		      streamReadRecord(streamID, varray, &nmiss);
-		      found ++;
+                   if( DBG ) fprintf( stderr,"Found V VEL in Varname %s\n",varname );
+                   streamReadRecord(streamID, varray, &nmiss);
+                   if ( nmiss ) cdoSetNAN(vlistInqVarMissval(vlistID, varID), gridsize, varray);
+                   found++;
 	  	 }	
 	       if( found == 2 )
 	    	 break;
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cdeff3..0b26ecf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -100,6 +100,8 @@ libcdo_la_SOURCES =            \
                percentiles.h   \
                pipe.c          \
                pipe.h          \
+               pmlist.c        \
+               pmlist.h        \
                pragma_omp_atomic_update.h \
                printinfo.h     \
                process.c       \
@@ -139,6 +141,7 @@ libcdo_la_SOURCES =            \
                timebase.h      \
                timer.c         \
                userlog.c       \
+               uthash.h        \
                util.c          \
                util.h          \
                zaxis.c
@@ -246,6 +249,7 @@ cdo_SOURCES += Adisit.c        \
                Isosurface.c    \
                Kvl.c           \
                Log.c           \
+	       MapReduce.c     \
                Maskbox.c       \
                Mastrfu.c       \
                Math.c          \
@@ -294,7 +298,7 @@ cdo_SOURCES += Adisit.c        \
                Setzaxis.c      \
                Showinfo.c      \
                Sinfo.c         \
-               Smooth9.c       \
+               Smooth.c        \
                Sort.c          \
                Sorttimestamp.c \
                Specinfo.c      \
@@ -305,7 +309,6 @@ cdo_SOURCES += Adisit.c        \
                Splitsel.c      \
                Splittime.c     \
                Splityear.c     \
-               SSOpar.c        \
                Subtrend.c      \
                Tee.c           \
                Templates.c     \
@@ -406,3 +409,8 @@ endif
 #	$(COMPILE) -DLOGPATH=${exec_prefix}/log -c -o cdo_static-userlog.o `test -f 'userlog.c' || echo '$(srcdir)/'`userlog.c
 #
 CLEANFILES  = `ls *~ 2> /dev/null`
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
diff --git a/src/Makefile.in b/src/Makefile.in
index a75a43f..2f333f6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -127,11 +127,11 @@ am_libcdo_la_OBJECTS = libcdo_la-cdo_pthread.lo libcdo_la-cdo_vlist.lo \
 	libcdo_la-namelist.lo libcdo_la-normal.lo \
 	libcdo_la-nth_element.lo libcdo_la-par_io.lo \
 	libcdo_la-percentiles_hist.lo libcdo_la-percentiles.lo \
-	libcdo_la-pipe.lo libcdo_la-process.lo libcdo_la-pstream.lo \
-	libcdo_la-pthread_debug.lo libcdo_la-readline.lo \
-	libcdo_la-realtime.lo libcdo_la-remaplib.lo \
-	libcdo_la-remapsort.lo libcdo_la-remap_scrip_io.lo \
-	libcdo_la-remap_search_reg2d.lo \
+	libcdo_la-pipe.lo libcdo_la-pmlist.lo libcdo_la-process.lo \
+	libcdo_la-pstream.lo libcdo_la-pthread_debug.lo \
+	libcdo_la-readline.lo libcdo_la-realtime.lo \
+	libcdo_la-remaplib.lo libcdo_la-remapsort.lo \
+	libcdo_la-remap_scrip_io.lo libcdo_la-remap_search_reg2d.lo \
 	libcdo_la-remap_search_latbins.lo \
 	libcdo_la-remap_store_link.lo \
 	libcdo_la-remap_store_link_cnsrv.lo libcdo_la-remap_conserv.lo \
@@ -193,11 +193,12 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
 	cdo-Intntime.$(OBJEXT) cdo-Inttime.$(OBJEXT) \
 	cdo-Intyear.$(OBJEXT) cdo-Invert.$(OBJEXT) \
 	cdo-Invertlev.$(OBJEXT) cdo-Isosurface.$(OBJEXT) \
-	cdo-Kvl.$(OBJEXT) cdo-Log.$(OBJEXT) cdo-Maskbox.$(OBJEXT) \
-	cdo-Mastrfu.$(OBJEXT) cdo-Math.$(OBJEXT) cdo-Merge.$(OBJEXT) \
-	cdo-Mergegrid.$(OBJEXT) cdo-Mergetime.$(OBJEXT) \
-	cdo-Merstat.$(OBJEXT) cdo-Monarith.$(OBJEXT) \
-	cdo-Mrotuv.$(OBJEXT) cdo-Mrotuvb.$(OBJEXT) cdo-Ninfo.$(OBJEXT) \
+	cdo-Kvl.$(OBJEXT) cdo-Log.$(OBJEXT) cdo-MapReduce.$(OBJEXT) \
+	cdo-Maskbox.$(OBJEXT) cdo-Mastrfu.$(OBJEXT) cdo-Math.$(OBJEXT) \
+	cdo-Merge.$(OBJEXT) cdo-Mergegrid.$(OBJEXT) \
+	cdo-Mergetime.$(OBJEXT) cdo-Merstat.$(OBJEXT) \
+	cdo-Monarith.$(OBJEXT) cdo-Mrotuv.$(OBJEXT) \
+	cdo-Mrotuvb.$(OBJEXT) cdo-Ninfo.$(OBJEXT) \
 	cdo-Nmltest.$(OBJEXT) cdo-Output.$(OBJEXT) \
 	cdo-Outputgmt.$(OBJEXT) cdo-Pack.$(OBJEXT) \
 	cdo-Pardup.$(OBJEXT) cdo-Pinfo.$(OBJEXT) \
@@ -215,21 +216,20 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(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-Sinfo.$(OBJEXT) cdo-Smooth.$(OBJEXT) cdo-Sort.$(OBJEXT) \
 	cdo-Sorttimestamp.$(OBJEXT) cdo-Specinfo.$(OBJEXT) \
 	cdo-Spectral.$(OBJEXT) cdo-Spectrum.$(OBJEXT) \
 	cdo-Split.$(OBJEXT) cdo-Splitrec.$(OBJEXT) \
 	cdo-Splitsel.$(OBJEXT) cdo-Splittime.$(OBJEXT) \
-	cdo-Splityear.$(OBJEXT) cdo-SSOpar.$(OBJEXT) \
-	cdo-Subtrend.$(OBJEXT) cdo-Tee.$(OBJEXT) \
-	cdo-Templates.$(OBJEXT) cdo-Test.$(OBJEXT) cdo-Tests.$(OBJEXT) \
-	cdo-Timedt.$(OBJEXT) cdo-Timcount.$(OBJEXT) \
-	cdo-Timpctl.$(OBJEXT) cdo-Timselpctl.$(OBJEXT) \
-	cdo-Timselstat.$(OBJEXT) cdo-Timsort.$(OBJEXT) \
-	cdo-Timstat.$(OBJEXT) cdo-Timstat2.$(OBJEXT) \
-	cdo-Timstat3.$(OBJEXT) cdo-Tinfo.$(OBJEXT) \
-	cdo-Tocomplex.$(OBJEXT) cdo-Transpose.$(OBJEXT) \
-	cdo-Trend.$(OBJEXT) cdo-Trms.$(OBJEXT) \
+	cdo-Splityear.$(OBJEXT) cdo-Subtrend.$(OBJEXT) \
+	cdo-Tee.$(OBJEXT) cdo-Templates.$(OBJEXT) cdo-Test.$(OBJEXT) \
+	cdo-Tests.$(OBJEXT) cdo-Timedt.$(OBJEXT) \
+	cdo-Timcount.$(OBJEXT) cdo-Timpctl.$(OBJEXT) \
+	cdo-Timselpctl.$(OBJEXT) cdo-Timselstat.$(OBJEXT) \
+	cdo-Timsort.$(OBJEXT) cdo-Timstat.$(OBJEXT) \
+	cdo-Timstat2.$(OBJEXT) cdo-Timstat3.$(OBJEXT) \
+	cdo-Tinfo.$(OBJEXT) cdo-Tocomplex.$(OBJEXT) \
+	cdo-Transpose.$(OBJEXT) cdo-Trend.$(OBJEXT) cdo-Trms.$(OBJEXT) \
 	cdo-Tstepcount.$(OBJEXT) cdo-Vargen.$(OBJEXT) \
 	cdo-Varrms.$(OBJEXT) cdo-Vertintml.$(OBJEXT) \
 	cdo-Vertintap.$(OBJEXT) cdo-Vertstat.$(OBJEXT) \
@@ -439,8 +439,6 @@ UDUNITS_LDFLAGS = @UDUNITS_LDFLAGS@
 USER_NAME = @USER_NAME@
 VERSION = @VERSION@
 XML2_LIBS = @XML2_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -516,17 +514,18 @@ libcdo_la_SOURCES = cdo_int.h compare.h cdo_pthread.c cdo_vlist.c \
 	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_hist.c percentiles_hist.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_write.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_store_link_cnsrv.c \
-	remap_store_link_cnsrv.h remap_conserv.c remap_conserv_scrip.c \
-	remap_distwgt.c remap_bicubic_scrip.c remap_bilinear_scrip.c \
-	stdnametable.c stdnametable.h specspace.c specspace.h \
-	statistic.c statistic.h table.c text.c text.h timebase.h \
-	timer.c userlog.c util.c util.h zaxis.c kdtreelib/kdtree.h \
+	percentiles.h pipe.c pipe.h pmlist.c pmlist.h \
+	pragma_omp_atomic_update.h printinfo.h process.c process.h \
+	pstream.c pstream.h pstream_write.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_store_link_cnsrv.c remap_store_link_cnsrv.h \
+	remap_conserv.c remap_conserv_scrip.c remap_distwgt.c \
+	remap_bicubic_scrip.c remap_bilinear_scrip.c stdnametable.c \
+	stdnametable.h specspace.c specspace.h statistic.c statistic.h \
+	table.c text.c text.h timebase.h timer.c userlog.c uthash.h \
+	util.c util.h zaxis.c kdtreelib/kdtree.h \
 	kdtreelib/kdtree_cartesian.c kdtreelib/kdtree_common.c \
 	kdtreelib/kdtree_spherical.c kdtreelib/pmergesort.c \
 	kdtreelib/pqueue.c kdtreelib/pqueue.h clipping/clipping.c \
@@ -559,27 +558,28 @@ cdo_SOURCES = cdo.c Adisit.c Afterburner.c Arith.c Arithc.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 Pardup.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 Timedt.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 Vargen.c \
-	Varrms.c Vertintml.c Vertintap.c Vertstat.c Vertcum.c \
-	Vertwind.c Verifygrid.c Wct.c Wind.c Writegrid.c Writerandom.c \
-	XTimstat.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 nearpt3c.h Magplot.c Magvector.c Maggraph.c \
-	template_parser.h template_parser.c results_template_parser.h \
+	MapReduce.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 Pardup.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 Smooth.c \
+	Sort.c Sorttimestamp.c Specinfo.c Spectral.c Spectrum.c \
+	Split.c Splitrec.c Splitsel.c Splittime.c Splityear.c \
+	Subtrend.c Tee.c Templates.c Test.c Tests.c Timedt.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 Vargen.c Varrms.c \
+	Vertintml.c Vertintap.c Vertstat.c Vertcum.c Vertwind.c \
+	Verifygrid.c Wct.c Wind.c Writegrid.c Writerandom.c XTimstat.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 \
+	nearpt3c.h Magplot.c Magvector.c Maggraph.c template_parser.h \
+	template_parser.c results_template_parser.h \
 	results_template_parser.c magics_template_parser.h \
 	magics_template_parser.c StringUtilities.h StringUtilities.c \
 	CdoMagicsMapper.h CdoMagicsMapper.c
@@ -856,6 +856,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Maggraph.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Magplot.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Magvector.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-MapReduce.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Maskbox.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Mastrfu.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Math.Po at am__quote@
@@ -883,7 +884,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Rotuv.Po at am__quote@
 @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@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-SSOpar.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@
@@ -905,7 +905,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Setzaxis.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Showinfo.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Sinfo.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Smooth9.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Smooth.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Sort.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Sorttimestamp.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Specinfo.Po at am__quote@
@@ -1026,6 +1026,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-percentiles.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-percentiles_hist.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-pipe.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-pmlist.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-process.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-pstream.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-pthread_debug.Plo at am__quote@
@@ -1480,6 +1481,13 @@ libcdo_la-pipe.lo: pipe.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c
 
+libcdo_la-pmlist.lo: pmlist.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-pmlist.lo -MD -MP -MF $(DEPDIR)/libcdo_la-pmlist.Tpo -c -o libcdo_la-pmlist.lo `test -f 'pmlist.c' || echo '$(srcdir)/'`pmlist.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-pmlist.Tpo $(DEPDIR)/libcdo_la-pmlist.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='pmlist.c' object='libcdo_la-pmlist.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-pmlist.lo `test -f 'pmlist.c' || echo '$(srcdir)/'`pmlist.c
+
 libcdo_la-process.lo: process.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-process.lo -MD -MP -MF $(DEPDIR)/libcdo_la-process.Tpo -c -o libcdo_la-process.lo `test -f 'process.c' || echo '$(srcdir)/'`process.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-process.Tpo $(DEPDIR)/libcdo_la-process.Plo
@@ -2817,6 +2825,20 @@ cdo-Log.obj: Log.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-Log.obj `if test -f 'Log.c'; then $(CYGPATH_W) 'Log.c'; else $(CYGPATH_W) '$(srcdir)/Log.c'; fi`
 
+cdo-MapReduce.o: MapReduce.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-MapReduce.o -MD -MP -MF $(DEPDIR)/cdo-MapReduce.Tpo -c -o cdo-MapReduce.o `test -f 'MapReduce.c' || echo '$(srcdir)/'`MapReduce.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-MapReduce.Tpo $(DEPDIR)/cdo-MapReduce.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='MapReduce.c' object='cdo-MapReduce.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-MapReduce.o `test -f 'MapReduce.c' || echo '$(srcdir)/'`MapReduce.c
+
+cdo-MapReduce.obj: MapReduce.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-MapReduce.obj -MD -MP -MF $(DEPDIR)/cdo-MapReduce.Tpo -c -o cdo-MapReduce.obj `if test -f 'MapReduce.c'; then $(CYGPATH_W) 'MapReduce.c'; else $(CYGPATH_W) '$(srcdir)/MapReduce.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-MapReduce.Tpo $(DEPDIR)/cdo-MapReduce.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='MapReduce.c' object='cdo-MapReduce.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-MapReduce.obj `if test -f 'MapReduce.c'; then $(CYGPATH_W) 'MapReduce.c'; else $(CYGPATH_W) '$(srcdir)/MapReduce.c'; fi`
+
 cdo-Maskbox.o: Maskbox.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Maskbox.o -MD -MP -MF $(DEPDIR)/cdo-Maskbox.Tpo -c -o cdo-Maskbox.o `test -f 'Maskbox.c' || echo '$(srcdir)/'`Maskbox.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Maskbox.Tpo $(DEPDIR)/cdo-Maskbox.Po
@@ -3489,19 +3511,19 @@ cdo-Sinfo.obj: Sinfo.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-Sinfo.obj `if test -f 'Sinfo.c'; then $(CYGPATH_W) 'Sinfo.c'; else $(CYGPATH_W) '$(srcdir)/Sinfo.c'; fi`
 
-cdo-Smooth9.o: Smooth9.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Smooth9.o -MD -MP -MF $(DEPDIR)/cdo-Smooth9.Tpo -c -o cdo-Smooth9.o `test -f 'Smooth9.c' || echo '$(srcdir)/'`Smooth9.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Smooth9.Tpo $(DEPDIR)/cdo-Smooth9.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Smooth9.c' object='cdo-Smooth9.o' libtool=no @AMDEPBACKSLASH@
+cdo-Smooth.o: Smooth.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Smooth.o -MD -MP -MF $(DEPDIR)/cdo-Smooth.Tpo -c -o cdo-Smooth.o `test -f 'Smooth.c' || echo '$(srcdir)/'`Smooth.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Smooth.Tpo $(DEPDIR)/cdo-Smooth.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Smooth.c' object='cdo-Smooth.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-Smooth9.o `test -f 'Smooth9.c' || echo '$(srcdir)/'`Smooth9.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Smooth.o `test -f 'Smooth.c' || echo '$(srcdir)/'`Smooth.c
 
-cdo-Smooth9.obj: Smooth9.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Smooth9.obj -MD -MP -MF $(DEPDIR)/cdo-Smooth9.Tpo -c -o cdo-Smooth9.obj `if test -f 'Smooth9.c'; then $(CYGPATH_W) 'Smooth9.c'; else $(CYGPATH_W) '$(srcdir)/Smooth9.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Smooth9.Tpo $(DEPDIR)/cdo-Smooth9.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Smooth9.c' object='cdo-Smooth9.obj' libtool=no @AMDEPBACKSLASH@
+cdo-Smooth.obj: Smooth.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Smooth.obj -MD -MP -MF $(DEPDIR)/cdo-Smooth.Tpo -c -o cdo-Smooth.obj `if test -f 'Smooth.c'; then $(CYGPATH_W) 'Smooth.c'; else $(CYGPATH_W) '$(srcdir)/Smooth.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Smooth.Tpo $(DEPDIR)/cdo-Smooth.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Smooth.c' object='cdo-Smooth.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-Smooth9.obj `if test -f 'Smooth9.c'; then $(CYGPATH_W) 'Smooth9.c'; else $(CYGPATH_W) '$(srcdir)/Smooth9.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 cdo-Smooth.obj `if test -f 'Smooth.c'; then $(CYGPATH_W) 'Smooth.c'; else $(CYGPATH_W) '$(srcdir)/Smooth.c'; fi`
 
 cdo-Sort.o: Sort.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Sort.o -MD -MP -MF $(DEPDIR)/cdo-Sort.Tpo -c -o cdo-Sort.o `test -f 'Sort.c' || echo '$(srcdir)/'`Sort.c
@@ -3643,20 +3665,6 @@ cdo-Splityear.obj: Splityear.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-Splityear.obj `if test -f 'Splityear.c'; then $(CYGPATH_W) 'Splityear.c'; else $(CYGPATH_W) '$(srcdir)/Splityear.c'; fi`
 
-cdo-SSOpar.o: SSOpar.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-SSOpar.o -MD -MP -MF $(DEPDIR)/cdo-SSOpar.Tpo -c -o cdo-SSOpar.o `test -f 'SSOpar.c' || echo '$(srcdir)/'`SSOpar.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-SSOpar.Tpo $(DEPDIR)/cdo-SSOpar.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='SSOpar.c' object='cdo-SSOpar.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-SSOpar.o `test -f 'SSOpar.c' || echo '$(srcdir)/'`SSOpar.c
-
-cdo-SSOpar.obj: SSOpar.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-SSOpar.obj -MD -MP -MF $(DEPDIR)/cdo-SSOpar.Tpo -c -o cdo-SSOpar.obj `if test -f 'SSOpar.c'; then $(CYGPATH_W) 'SSOpar.c'; else $(CYGPATH_W) '$(srcdir)/SSOpar.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-SSOpar.Tpo $(DEPDIR)/cdo-SSOpar.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='SSOpar.c' object='cdo-SSOpar.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-SSOpar.obj `if test -f 'SSOpar.c'; then $(CYGPATH_W) 'SSOpar.c'; else $(CYGPATH_W) '$(srcdir)/SSOpar.c'; fi`
-
 cdo-Subtrend.o: Subtrend.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Subtrend.o -MD -MP -MF $(DEPDIR)/cdo-Subtrend.Tpo -c -o cdo-Subtrend.o `test -f 'Subtrend.c' || echo '$(srcdir)/'`Subtrend.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Subtrend.Tpo $(DEPDIR)/cdo-Subtrend.Po
@@ -4589,7 +4597,7 @@ maintainer-clean-generic:
 	@echo "it deletes files that may require special tools to rebuild."
 clean: clean-am
 
-clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \
 	clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am
 
 distclean: distclean-am
@@ -4661,7 +4669,7 @@ uninstall-am: uninstall-binPROGRAMS
 .MAKE: all install-am install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
-	clean-binPROGRAMS clean-generic clean-libtool \
+	clean-binPROGRAMS clean-generic clean-libtool clean-local \
 	clean-noinstLTLIBRARIES clean-noinstPROGRAMS cscopelist-am \
 	ctags ctags-am distclean distclean-compile distclean-generic \
 	distclean-hdr distclean-libtool distclean-tags distdir dvi \
@@ -4676,6 +4684,11 @@ uninstall-am: uninstall-binPROGRAMS
 	pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
 	uninstall-binPROGRAMS
 
+#
+clean-local: clean-local-dirs
+.PHONY: clean-local-dirs
+clean-local-dirs:
+	-rm -rf *.dSYM
 
 # 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/src/MapReduce.c b/src/MapReduce.c
new file mode 100644
index 0000000..1f6de22
--- /dev/null
+++ b/src/MapReduce.c
@@ -0,0 +1,220 @@
+/*
+  This file is part of CDO. CDO is a collection of Operators to
+  manipulate and analyse Climate model Data.
+
+  Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.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.
+*/
+
+/*
+  This module contains the following operators:
+
+  Pack      reduce
+*/
+
+#if defined(_OPENMP)
+#  include <omp.h>
+#endif
+
+#include <limits.h>
+
+#include <cdi.h>
+#include "cdo.h"
+#include "cdo_int.h"
+#include "grid.h"
+
+/* read only the first data variable from input filename into a given double
+ * pointer */
+/* DON'T MOVE IT! is necessary to have the pstream.h file included AFTER this
+ * function definition */
+void read_first_record(char *filename, int gridSize, double *field)
+{
+  int nmiss,varID,levelID;
+  int streamID = streamOpenRead(filename);
+  streamInqTimestep(streamID,0);
+  streamInqRecord(streamID,&varID,&levelID);
+  streamReadRecord(streamID, field, &nmiss);
+  streamClose(streamID);
+}
+
+#include "pstream.h"
+
+/*
+ * count the number of locations, for which the mask is TRUE
+ * */
+int countMask(double *maskField, int gridSize, double falseVal)
+{
+  int counter;
+
+  counter = 0;
+
+  for (int i = 0; i < gridSize; i++)
+    {
+      if (!DBL_IS_EQUAL(maskField[i],falseVal)) counter += 1;
+    }
+  return counter;
+}
+
+/* 
+ * the operators argument has to be a single horizontal field,
+ * non-zero values are used to mark the relevant locations
+ */
+void *MapReduce(void *argument)
+{
+  int nrecs;
+  int tsID;
+  int varID, levelID, recID;
+  int nmiss;
+  int nobounds = FALSE;
+  int nocoords = FALSE;
+  /*double missval1, missval2; */
+
+  cdoInitialize(argument);
+
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  /* check input grid type and size - this will be used for selecting relevant
+   * variables from the input file*/
+  int inputGridID   = cdoDefineGrid(operatorArgv()[0]);
+  int inputGridSize = gridInqSize(inputGridID);
+  int inputGridType = gridInqType(inputGridID);
+  if ( cdoDebug ) cdoPrint("MapReduce: input gridSize:%d", inputGridSize);
+
+  /* creata an index list of the relevant locations  {{{ */
+  tsID = 0;
+  double *inputMaskField = (double*) Malloc(inputGridSize*sizeof(double));
+  read_first_record(operatorArgv()[0],inputGridSize, inputMaskField);
+
+  /* non-zero values mark the relevant points */
+  int maskSize = countMask(inputMaskField, inputGridSize, 0.0);
+  if ( cdoDebug ) cdoPrint("MapReduce: maskSize = %d",maskSize);
+
+  int *maskIndexList = (int *) Malloc(maskSize*sizeof(int));
+  for (int m = 0; m < maskSize; m++) maskIndexList[m] = -1;
+
+  int k = 0;
+  for (int i = 0; i < inputGridSize; i++)
+    {
+      if (!DBL_IS_EQUAL(inputMaskField[i],0.0))
+        {
+          maskIndexList[k] = i;
+          k += 1;
+        }
+    }
+  /* }}} */
+
+  /* check if coordinated bounds shound not be created */
+  if ( 2 <= operatorArgc() )
+  {
+    char *coordinatesLimitation = operatorArgv()[1];
+    if ( 0 == strncmp("nobounds",coordinatesLimitation,8) ) nobounds = TRUE;
+    if ( 0 == strncmp("nocoords",coordinatesLimitation,8) ) nocoords = TRUE;
+  }
+  /* create unstructured output grid including bounds*/
+  int outputGridID = gridToUnstructuredSelecton(inputGridID, maskSize, maskIndexList, nocoords, nobounds);
+
+  /* create output vlist: Only variabes which have the same gridtype and
+   * gridsize as the input mask should be proessed. Everything else is ignoreds
+   * {{{ */
+  int vlistID1  = streamInqVlist(streamID1);
+  int nvars     = vlistNvars(vlistID1);
+  int *vars     = (int*) Malloc(nvars*sizeof(int));
+
+  /* use vlist flags for marking the corresponding variables */
+  vlistClearFlag(vlistID1);
+  for ( varID = 0; varID < nvars; varID++ )
+    {
+      vars[varID] = FALSE;
+
+      int gridID = vlistInqVarGrid(vlistID1, varID);
+      if (inputGridType == gridInqType(gridID) && inputGridSize == gridInqSize(gridID))
+        {
+          vars[varID] = TRUE;
+          int zaxisID  = vlistInqVarZaxis(vlistID1, varID);
+          int nlevs    = zaxisInqSize(zaxisID);
+          for ( int levID = 0; levID < nlevs; levID++ )
+            {
+              vlistDefFlag(vlistID1, varID, levID, TRUE);
+            }
+        }
+    }
+  int vlistID2 = vlistCreate();
+  vlistCopyFlag(vlistID2, vlistID1);
+  /* }}} */
+
+  int taxisID1  = vlistInqTaxis(vlistID1);
+  int taxisID2  = taxisDuplicate(taxisID1);
+  vlistDefTaxis(vlistID2, taxisID2);
+
+  /* use the new selection grid for all output variables */
+  int ngrids = vlistNgrids(vlistID2);
+  for ( int index = 0; index < ngrids; index++ ) vlistChangeGridIndex(vlistID2, index, outputGridID);
+
+  /* loop over input fields and mask the data values {{{ */
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  streamDefVlist(streamID2, vlistID2);
+
+  double *arrayIn  = (double *)Malloc(inputGridSize*sizeof(double));
+  double *arrayOut = (double *)Malloc(maskSize*sizeof(double));
+
+  tsID = 0; 
+  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+    {
+      taxisCopyTimestep(taxisID2, taxisID1);
+      streamDefTimestep(streamID2, tsID);
+
+      for ( recID = 0; recID < nrecs; recID++ )
+        {
+          streamInqRecord(streamID1, &varID, &levelID);
+          if (TRUE == vars[varID])
+            {
+              int varID2   = vlistFindVar(vlistID2, varID);
+              int levelID2 = vlistFindLevel(vlistID2, varID, levelID);
+
+              streamReadRecord(streamID1, arrayIn, &nmiss);
+
+              for (int i = 0; i < maskSize;  i++)
+                arrayOut[i] = arrayIn[maskIndexList[i]];
+
+
+              streamDefRecord(streamID2, varID2, levelID2);
+              streamWriteRecord(streamID2, arrayOut, 0);
+
+            }
+        }
+      tsID++;
+    }
+  /* }}} */
+
+
+  streamClose(streamID2);
+  streamClose(streamID1);
+
+  Free(vars);
+  Free(arrayOut);
+  Free(arrayIn);
+  Free(inputMaskField);
+  Free(maskIndexList);
+
+  cdoFinish();
+
+  return 0;
+}
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/Math.c b/src/Math.c
index 013432c..7412d42 100644
--- a/src/Math.c
+++ b/src/Math.c
@@ -44,21 +44,10 @@
 void *Math(void *argument)
 {
   enum {ABS, FINT, FNINT, SQR, SQRT, EXP, LN, LOG10, SIN, COS, TAN, ASIN, ACOS, ATAN, POW, RECI};
-  int operatorID;
-  int operfunc;
-  int streamID1, streamID2;
-  int gridsize;
-  int nrecs, recID;
-  int tsID;
+  int nrecs;
   int varID, levelID;
-  int vlistID1, vlistID2;
   int nmiss, nmiss2;
   int i;
-  int number;
-  double missval1;
-  double *array1, *array2;
-  double rc = 0;
-  int taxisID1, taxisID2;
 
   cdoInitialize(argument);
 
@@ -79,49 +68,50 @@ void *Math(void *argument)
   cdoOperatorAdd("pow",   POW,   0, NULL);
   cdoOperatorAdd("reci",  RECI,  0, NULL);
  
-  operatorID = cdoOperatorID();
-  operfunc = cdoOperatorF1(operatorID);
+  int operatorID = cdoOperatorID();
+  int operfunc = cdoOperatorF1(operatorID);
 
+  double rc = 0;
   if ( operfunc == POW )
     {
       operatorInputArg("value");
       rc = parameter2double(operatorArgv()[0]);
     }
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  gridsize = vlistGridsizeMax(vlistID1);
+  int gridsize = vlistGridsizeMax(vlistID1);
   if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
 
-  array1 = (double*) Malloc(gridsize*sizeof(double));
-  array2 = (double*) Malloc(gridsize*sizeof(double));
+  double *array1 = (double*) Malloc(gridsize*sizeof(double));
+  double *array2 = (double*) Malloc(gridsize*sizeof(double));
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
 
       streamDefTimestep(streamID2, tsID);
 
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  streamReadRecord(streamID1, array1, &nmiss);
 
-	  missval1 = vlistInqVarMissval(vlistID1, varID);
+	  double missval1 = vlistInqVarMissval(vlistID1, varID);
 	  gridsize = gridInqSize(vlistInqVarGrid(vlistID1, varID));
-          number   = vlistInqVarNumber(vlistID1, varID);
+          int number   = vlistInqVarNumber(vlistID1, varID);
 
           if ( number == CDI_REAL )
             {
@@ -137,7 +127,7 @@ void *Math(void *argument)
                   break;
                 case FNINT:
                   for ( i = 0; i < gridsize; i++ )
-                    array2[i] = DBL_IS_EQUAL(array1[i], missval1) ? missval1 : round(array1[i]);
+                    array2[i] = DBL_IS_EQUAL(array1[i], missval1) ? missval1 : (double)lround(array1[i]);
                   break;
                 case SQR:
                   for ( i = 0; i < gridsize; i++ )
diff --git a/src/Merge.c b/src/Merge.c
index 3f30447..efa638f 100644
--- a/src/Merge.c
+++ b/src/Merge.c
@@ -133,14 +133,13 @@ void *Merge(void *argument)
   int nrecs = 0;
   int recID, levelID, levelID2;
   int index;
-  int lcopy = FALSE;
   int gridsize;
   int nmiss;
   //int skip_same_var = FALSE;
 
   cdoInitialize(argument);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
   /*
   {
@@ -165,10 +164,8 @@ void *Merge(void *argument)
 
   const char *ofilename = cdoStreamName(streamCnt-1)->args;
 
-  if ( !cdoSilentMode && !cdoOverwriteMode )
-    if ( fileExists(ofilename) )
-      if ( !userFileOverwrite(ofilename) )
-	cdoAbort("Outputfile %s already exists!", ofilename);
+  if ( !cdoOverwriteMode && fileExists(ofilename) && !userFileOverwrite(ofilename) )
+    cdoAbort("Outputfile %s already exists!", ofilename);
 
   int *streamIDs = (int*) Malloc(nmerge*sizeof(int));
   int *vlistIDs  = (int*) Malloc(nmerge*sizeof(int));
diff --git a/src/Mergetime.c b/src/Mergetime.c
index 7b97a70..19c8a05 100644
--- a/src/Mergetime.c
+++ b/src/Mergetime.c
@@ -36,12 +36,11 @@ void *Mergetime(void *argument)
   int vlistID1, vlistID2;
   int fileID;
   int taxisID1, taxisID2 = CDI_UNDEFID;
-  int lcopy = FALSE;
   int nmiss;
   int vdate, vtime;
   int last_vdate = -1, last_vtime = -1;
   int next_fileID;
-  int skip_same_time = FALSE;
+  bool skip_same_time = false;
   double *array = NULL;
   typedef struct
   {
@@ -65,14 +64,14 @@ void *Mergetime(void *argument)
 	ival = atoi(envstr);
 	if ( ival == 1 )
 	  {
-	    skip_same_time = TRUE;
+	    skip_same_time = true;
 	    if ( cdoVerbose )
 	      cdoPrint("Set SKIP_SAME_TIME to %d", ival);
 	  }
       }
   }
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
   int nfiles = cdoStreamCnt() - 1;
 
@@ -116,10 +115,8 @@ void *Mergetime(void *argument)
 
   const char *ofilename = cdoStreamName(nfiles)->args;
 
-  if ( !cdoSilentMode && !cdoOverwriteMode )
-    if ( fileExists(ofilename) )
-      if ( !userFileOverwrite(ofilename) )
-	cdoAbort("Outputfile %s already exists!", ofilename);
+  if ( !cdoOverwriteMode && fileExists(ofilename) && !userFileOverwrite(ofilename) )
+    cdoAbort("Outputfile %s already exists!", ofilename);
 
   int streamID2 = streamOpenWrite(cdoStreamName(nfiles), cdoFiletype());
 
diff --git a/src/Monarith.c b/src/Monarith.c
index 1440e16..a15717a 100644
--- a/src/Monarith.c
+++ b/src/Monarith.c
@@ -130,7 +130,7 @@ void *Monarith(void *argument)
 	      year2 = yearmon2/100;
 	      mon2  = yearmon2 - (yearmon2/100)*100;
 
-	      cdoAbort("Timestep %d in %s has wrong date!\nCurrent year=%4d mon=%2d, expected year=%4d mon=%2d",
+	      cdoAbort("Timestep %d in %s has wrong date! Current year=%4d mon=%2d, expected year=%4d mon=%2d",
 		       tsID2+1, cdoStreamName(1)->args, year2, mon2, year1, mon1);
 	    }
 
diff --git a/src/Mrotuvb.c b/src/Mrotuvb.c
index 749c7df..b1337a4 100644
--- a/src/Mrotuvb.c
+++ b/src/Mrotuvb.c
@@ -63,13 +63,13 @@ void rotate_uv2(double *u_i, double *v_j, int ix, int iy,
   double lat_factor;
   double absold, absnew;  /* velocity vector lengths */
   int  i, j, ip1, im1, jp1, jm1;
-  int  change_sign_u, change_sign_v;
+  bool change_sign_u, change_sign_v;
   double pi = 3.14159265359;
 
 
   /* specification whether change in sign is needed for the input arrays */
-  change_sign_u = FALSE;
-  change_sign_v = TRUE;
+  change_sign_u = false;
+  change_sign_v = true;
 
   /* initialization */
   for ( i = 0; i < ix*iy; i++ )
@@ -259,47 +259,31 @@ void uv_to_p_grid(int nlon, int nlat, double *grid1x, double *grid1y,
 
 void *Mrotuvb(void *argument)
 {
-  int streamID1, streamID2, streamID3;
   int nrecs, nrecs2;
-  int tsID, recID, levelID;
+  int levelID;
   int varID1, varID2;
-  int nvars;
-  int gridID1, gridID2, gridID3;
-  int gridsize;
-  int nlon, nlat;
-  int vlistID1, vlistID2, vlistID3;
-  int i, j;
-  int taxisID1, taxisID3;
   int nmiss1, nmiss2;
-  int code1, code2;
-  int gpint = TRUE;
-  double missval1, missval2;
-  double *ufield = NULL, *vfield = NULL;
-  double *urfield = NULL, *vrfield = NULL;
-  double *uhelp = NULL, *vhelp = NULL;
-  double *grid1x = NULL, *grid2x = NULL, *grid3x = NULL;
-  double *grid1y = NULL, *grid2y = NULL, *grid3y = NULL;
+  bool gpint = true;
 
   cdoInitialize(argument);
 
   if ( operatorArgc() == 1 )
-    if ( strcmp(operatorArgv()[0], "noint") == 0 )
-      gpint = FALSE;
+    if ( strcmp(operatorArgv()[0], "noint") == 0 ) gpint = false;
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
-  streamID2 = streamOpenRead(cdoStreamName(1));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID2 = streamOpenRead(cdoStreamName(1));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = streamInqVlist(streamID2);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = streamInqVlist(streamID2);
 
-  nvars = vlistNvars(vlistID1);
+  int nvars = vlistNvars(vlistID1);
   if ( nvars > 1 ) cdoAbort("More than one variable found in %s",  cdoStreamName(0)->args);
   nvars = vlistNvars(vlistID2);
   if ( nvars > 1 ) cdoAbort("More than one variable found in %s",  cdoStreamName(1)->args);
 
-  gridID1 = vlistGrid(vlistID1, 0);
-  gridID2 = vlistGrid(vlistID2, 0);
-  gridsize = gridInqSize(gridID1);
+  int gridID1 = vlistGrid(vlistID1, 0);
+  int gridID2 = vlistGrid(vlistID2, 0);
+  int gridsize = gridInqSize(gridID1);
   if ( gpint == TRUE  && gridID1 == gridID2 ) cdoAbort("Input grids are the same, use parameter >noint< to disable interpolation!");
   if ( gpint == FALSE && gridID1 != gridID2 ) cdoAbort("Input grids are not the same!");
   if ( gridsize != gridInqSize(gridID2) ) cdoAbort("Grids have different size!");
@@ -319,15 +303,15 @@ void *Mrotuvb(void *argument)
 
   if ( gridsize != gridInqSize(gridID2) ) cdoAbort("Internal problem: gridsize changed!");
 
-  nlon    = gridInqXsize(gridID1);
-  nlat    = gridInqYsize(gridID1);
+  int nlon    = gridInqXsize(gridID1);
+  int nlat    = gridInqYsize(gridID1);
 
-  grid1x  = (double*) Malloc(gridsize*sizeof(double));
-  grid1y  = (double*) Malloc(gridsize*sizeof(double));
-  grid2x  = (double*) Malloc(gridsize*sizeof(double));
-  grid2y  = (double*) Malloc(gridsize*sizeof(double));
-  grid3x  = (double*) Malloc(gridsize*sizeof(double));
-  grid3y  = (double*) Malloc(gridsize*sizeof(double));
+  double *grid1x  = (double*) Malloc(gridsize*sizeof(double));
+  double *grid1y  = (double*) Malloc(gridsize*sizeof(double));
+  double *grid2x  = (double*) Malloc(gridsize*sizeof(double));
+  double *grid2y  = (double*) Malloc(gridsize*sizeof(double));
+  double *grid3x  = (double*) Malloc(gridsize*sizeof(double));
+  double *grid3y  = (double*) Malloc(gridsize*sizeof(double));
 
   gridInqXvals(gridID1, grid1x);
   gridInqYvals(gridID1, grid1y);
@@ -368,49 +352,50 @@ void *Mrotuvb(void *argument)
   if ( grid2x ) Free(grid2x);
   if ( grid2y ) Free(grid2y);
 
-  gridID3 = gridCreate(GRID_CURVILINEAR, gridsize);
+  int gridID3 = gridCreate(GRID_CURVILINEAR, gridsize);
   gridDefPrec(gridID3, gridInqPrec(gridID1));
   gridDefXsize(gridID3, nlon);
   gridDefYsize(gridID3, nlat);
   gridDefXvals(gridID3, grid3x);
   gridDefYvals(gridID3, grid3y);
 
-  for ( i = 0; i < gridsize; i++ )
+  for ( int i = 0; i < gridsize; i++ )
     {
       grid3x[i] *= DEG2RAD;
       grid3y[i] *= DEG2RAD;
     }
 
-  vlistID3 = vlistCreate();
+  int vlistID3 = vlistCreate();
   vlistCopy(vlistID3, vlistID1);
   vlistCat(vlistID3, vlistID2);
 
-  code1 = vlistInqVarCode(vlistID1, 0);
-  code2 = vlistInqVarCode(vlistID2, 0);
+  int code1 = vlistInqVarCode(vlistID1, 0);
+  int code2 = vlistInqVarCode(vlistID2, 0);
 
   if ( code1 == code2 ) vlistDefVarCode(vlistID3, 1, code1+1);
   
   vlistChangeGrid(vlistID3, gridID1, gridID3);
   vlistChangeGrid(vlistID3, gridID2, gridID3);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID3 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID3 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID3, taxisID3);
 
   if ( cdoVerbose ) vlistPrint(vlistID3);
 
-  streamID3 = streamOpenWrite(cdoStreamName(2), cdoFiletype());
+  int streamID3 = streamOpenWrite(cdoStreamName(2), cdoFiletype());
 
   streamDefVlist(streamID3, vlistID3);
 
-  missval1 = vlistInqVarMissval(vlistID1, 0);
-  missval2 = vlistInqVarMissval(vlistID2, 0);
+  double missval1 = vlistInqVarMissval(vlistID1, 0);
+  double missval2 = vlistInqVarMissval(vlistID2, 0);
 
-  ufield  = (double*) Malloc(gridsize*sizeof(double));
-  vfield  = (double*) Malloc(gridsize*sizeof(double));
-  urfield = (double*) Malloc(gridsize*sizeof(double));
-  vrfield = (double*) Malloc(gridsize*sizeof(double));
+  double *ufield  = (double*) Malloc(gridsize*sizeof(double));
+  double *vfield  = (double*) Malloc(gridsize*sizeof(double));
+  double *urfield = (double*) Malloc(gridsize*sizeof(double));
+  double *vrfield = (double*) Malloc(gridsize*sizeof(double));
 
+  double *uhelp = NULL, *vhelp = NULL;
   if ( gpint )
     {
       int gridsizex = (nlon+2)*nlat;
@@ -418,7 +403,7 @@ void *Mrotuvb(void *argument)
       vhelp   = (double*) Malloc(gridsizex*sizeof(double));
     }
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID3, taxisID1);
@@ -429,7 +414,7 @@ void *Mrotuvb(void *argument)
 
       if ( nrecs != nrecs2 ) cdoAbort("Input streams have different number of levels!");
 	       
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID1, &levelID);
 	  streamInqRecord(streamID2, &varID2, &levelID);
@@ -440,7 +425,7 @@ void *Mrotuvb(void *argument)
 	  /* remove missing values */
 	  if ( nmiss1 || nmiss2 )
 	    {
-	      for ( i = 0; i < gridsize; i++ )
+	      for ( int i = 0; i < gridsize; i++ )
 		{
 		  if ( DBL_IS_EQUAL(ufield[i], missval1) ) ufield[i] = 0;
 		  if ( DBL_IS_EQUAL(vfield[i], missval2) ) vfield[i] = 0;
@@ -450,15 +435,15 @@ void *Mrotuvb(void *argument)
 	  if ( gpint )
 	    {
 	      /* load to a help field */
-	      for ( j = 0; j < nlat; j++ )
-		for ( i = 0; i < nlon; i++ )
+	      for ( int j = 0; j < nlat; j++ )
+		for ( int i = 0; i < nlon; i++ )
 		  {
 		    uhelp[IX2D(j,i+1,nlon+2)] = ufield[IX2D(j,i,nlon)];
 		    vhelp[IX2D(j,i+1,nlon+2)] = vfield[IX2D(j,i,nlon)];
 		  }
 
 	      /* make help field cyclic */
-	      for ( j = 0; j < nlat; j++ )
+	      for ( int j = 0; j < nlat; j++ )
 		{
 		  uhelp[IX2D(j,0,nlon+2)]      = uhelp[IX2D(j,nlon,nlon+2)];
 		  uhelp[IX2D(j,nlon+1,nlon+2)] = uhelp[IX2D(j,1,nlon+2)];
@@ -467,15 +452,15 @@ void *Mrotuvb(void *argument)
 		}
 
 	      /* interpolate on pressure points */
-	      for ( j = 1; j < nlat; j++ )
-		for ( i = 0; i < nlon; i++ )
+	      for ( int j = 1; j < nlat; j++ )
+		for ( int i = 0; i < nlon; i++ )
 		  {
 		    ufield[IX2D(j,i,nlon)] = (uhelp[IX2D(j,i,nlon+2)]+uhelp[IX2D(j,i+1,nlon+2)])*0.5;
 		    vfield[IX2D(j,i,nlon)] = (vhelp[IX2D(j-1,i+1,nlon+2)]+vhelp[IX2D(j,i+1,nlon+2)])*0.5;
 		  }
 	    }
 
-	  for ( i = 0; i < nlon; i++ )
+	  for ( int i = 0; i < nlon; i++ )
 	    {
 	      ufield[IX2D(0,i,nlon)] = 0;
 	      vfield[IX2D(0,i,nlon)] = 0;
@@ -489,8 +474,8 @@ void *Mrotuvb(void *argument)
 	  /*
           {
 	  double lat, lon, auv, alpha;
-	  for ( j = 1; j < nlat-1; j += 3 )
-	    for ( i = 0; i < nlon; i += 3 )
+	  for ( int j = 1; j < nlat-1; j += 3 )
+	    for ( int i = 0; i < nlon; i += 3 )
 	      {
 		lat = grid3y[IX2D(j,i,nlon)]*RAD2DEG;
 		lon = grid3x[IX2D(j,i,nlon)]*RAD2DEG; 
diff --git a/src/Ninfo.c b/src/Ninfo.c
index 607c205..7d9f503 100644
--- a/src/Ninfo.c
+++ b/src/Ninfo.c
@@ -24,6 +24,8 @@
       Ninfo      nmon            Number of months
       Ninfo      ndate           Number of dates
       Ninfo      ntime           Number of timesteps
+      Ninfo      ngridpoints     Number of gridpoints
+      Ninfo      ngrids          Number of grids
 */
 
 
@@ -35,13 +37,14 @@
 
 void *Ninfo(void *argument)
 {
-  enum {NYEAR, NMON, NDATE, NTIME, NPAR, NLEVEL};
+  enum {NYEAR, NMON, NDATE, NTIME, NPAR, NLEVEL, NGRIDPOINTS, NGRIDS};
   int operatorID;
   int operfunc;
-  int varID, zaxisID;
+  int varID, zaxisID, gridID;
   int vdate;
-  int nrecs, nvars, ntsteps;
+  int nrecs, nvars, ntsteps, ngrids;
   int levelsize;
+  int gridsize;
   int tsID, ndate, date0 = 0;
   int day, mon0 = 0, mon, nmon, year0 = 0, year, nyear;
   int taxisID;
@@ -50,12 +53,14 @@ void *Ninfo(void *argument)
 
   cdoInitialize(argument);
 
-  cdoOperatorAdd("nyear",  NYEAR,  0, NULL);
-  cdoOperatorAdd("nmon",   NMON,   0, NULL);
-  cdoOperatorAdd("ndate",  NDATE,  0, NULL);
-  cdoOperatorAdd("ntime",  NTIME,  0, NULL);
-  cdoOperatorAdd("npar",   NPAR,   0, NULL);
-  cdoOperatorAdd("nlevel", NLEVEL, 0, NULL);
+  cdoOperatorAdd("nyear"       , NYEAR       , 0 , NULL);
+  cdoOperatorAdd("nmon"        , NMON        , 0 , NULL);
+  cdoOperatorAdd("ndate"       , NDATE       , 0 , NULL);
+  cdoOperatorAdd("ntime"       , NTIME       , 0 , NULL);
+  cdoOperatorAdd("npar"        , NPAR        , 0 , NULL);
+  cdoOperatorAdd("nlevel"      , NLEVEL      , 0 , NULL);
+  cdoOperatorAdd("ngridpoints" , NGRIDPOINTS , 0 , NULL);
+  cdoOperatorAdd("ngrids"      , NGRIDS      , 0 , NULL);
 
   operatorID = cdoOperatorID();
   operfunc   = cdoOperatorF1(operatorID);
@@ -67,6 +72,7 @@ void *Ninfo(void *argument)
   nvars   = vlistNvars(vlistID);
   taxisID = vlistInqTaxis(vlistID);
   ntsteps = vlistNtsteps(vlistID);
+  ngrids  = vlistNgrids(vlistID);
 
   switch ( operfunc )
     {
@@ -145,6 +151,17 @@ void *Ninfo(void *argument)
 	  fprintf(stdout, "%d\n", levelsize);
 	}
       break;
+    case NGRIDPOINTS:
+      for ( varID = 0; varID < nvars; varID++ )
+	{
+	  gridID = vlistInqVarGrid(vlistID, varID);
+	  gridsize = gridInqSize(gridID);
+	  fprintf(stdout, "%d\n", gridsize);
+	}
+      break;
+    case NGRIDS:
+      fprintf(stdout, "%d\n", ngrids);
+      break;
     default:
       cdoAbort("operator not implemented!");
       break;
diff --git a/src/Output.c b/src/Output.c
index 4ddfdd8..e954d57 100644
--- a/src/Output.c
+++ b/src/Output.c
@@ -73,7 +73,7 @@ void *Output(void *argument)
   int nKeys;
   int Keylen[]           = {      0,        8,      11,      4,      8,     6,     6,     6,     6,      4,      4,          6,     10,      8,      5,       2,     2 };
   enum                     {knohead,   kvalue,  kparam,  kcode,  kname,  klon,  klat,  klev,  kbin,  kxind,  kyind,  ktimestep,  kdate,  ktime,  kyear,  kmonth,  kday };
-  const char *Keynames[] = {"nohead", "value", "param", "code", "name", "lon", "lat", "lev", "bin", "xind", "yind", "timestep", "date", "time", "year", "month", "day"};
+  const char *Keynames[] = {"nohead",  "value", "param", "code", "name", "lon", "lat", "lev", "bin", "xind", "yind", "timestep", "date", "time", "year", "month", "day"};
 
 
   cdoInitialize(argument);
@@ -309,23 +309,26 @@ void *Output(void *argument)
 		      for ( k = 0; k < nkeys; ++k )
 			{
 			  len = Keylen[keys[k]];
-			  if      ( keys[k] == kvalue    ) fprintf(stdout, "%*g ", len, array[i]);
-			  else if ( keys[k] == kparam    ) fprintf(stdout, "%*s ", len, paramstr);
-			  else if ( keys[k] == kcode     ) fprintf(stdout, "%*d ", len, code);
-			  else if ( keys[k] == kname     ) fprintf(stdout, "%*s ", len, name);
-			  else if ( keys[k] == klon      ) fprintf(stdout, "%*g ", len, lon);
-			  else if ( keys[k] == klat      ) fprintf(stdout, "%*g ", len, lat);
-			  else if ( keys[k] == klev      ) fprintf(stdout, "%*g ", len, level);
-			  else if ( keys[k] == kbin      ) fprintf(stdout, "%*g ", len, level);
-			  else if ( keys[k] == kxind     ) fprintf(stdout, "%*d ", len, xind+1);
-			  else if ( keys[k] == kyind     ) fprintf(stdout, "%*d ", len, yind+1);
-			  else if ( keys[k] == ktimestep ) fprintf(stdout, "%*d ", len, tsID+1);
-			  else if ( keys[k] == kdate     ) fprintf(stdout, "%*s ", len, vdatestr);
-			  else if ( keys[k] == ktime     ) fprintf(stdout, "%*s ", len, vtimestr);
-			  else if ( keys[k] == kyear     ) fprintf(stdout, "%*d ", len, year);
-			  else if ( keys[k] == kmonth    ) fprintf(stdout, "%*d ", len, month);
-			  else if ( keys[k] == kday      ) fprintf(stdout, "%*d ", len, day);
-			}
+                          switch ( keys[k] )
+                            {
+                            case kvalue:     fprintf(stdout, "%*g ", len, array[i]); break;
+                            case kparam:     fprintf(stdout, "%*s ", len, paramstr); break;
+                            case kcode:      fprintf(stdout, "%*d ", len, code); break;
+                            case kname:      fprintf(stdout, "%*s ", len, name); break;
+                            case klon:       fprintf(stdout, "%*g ", len, lon); break;
+                            case klat:       fprintf(stdout, "%*g ", len, lat); break;
+                            case klev:       fprintf(stdout, "%*g ", len, level); break;
+                            case kbin:       fprintf(stdout, "%*g ", len, level); break;
+                            case kxind:      fprintf(stdout, "%*d ", len, xind+1); break;
+                            case kyind:      fprintf(stdout, "%*d ", len, yind+1); break;
+                            case ktimestep:  fprintf(stdout, "%*d ", len, tsID+1); break;
+                            case kdate:      fprintf(stdout, "%*s ", len, vdatestr); break;
+                            case ktime:      fprintf(stdout, "%*s ", len, vtimestr); break;
+                            case kyear:      fprintf(stdout, "%*d ", len, year); break;
+                            case kmonth:     fprintf(stdout, "%*d ", len, month); break;
+                            case kday:       fprintf(stdout, "%*d ", len, day); break;
+                            }
+                        }
 		      fprintf(stdout, "\n");
 		    }
 		}
diff --git a/src/Outputgmt.c b/src/Outputgmt.c
index 75c3cb9..0735f58 100644
--- a/src/Outputgmt.c
+++ b/src/Outputgmt.c
@@ -707,7 +707,7 @@ void *Outputgmt(void *argument)
 		    }
 		  else if ( lhov )
 		    {
-		      cdoAbort("Implementation for hovmoeller data missing!\n");
+		      cdoAbort("Implementation for hovmoeller data missing!");
 		    }
 		  else
 		    {
diff --git a/src/Pressure.c b/src/Pressure.c
index 471f785..9579aa5 100644
--- a/src/Pressure.c
+++ b/src/Pressure.c
@@ -44,26 +44,21 @@ void *Pressure(void *argument)
   int recID, nrecs;
   int i, k, offset;
   int tsID, varID, levelID;
-  int nvars;
-  int zaxisIDp, zaxisIDh = -1, nzaxis;
+  int zaxisIDp, zaxisIDh = -1;
   int gridID, zaxisID;
-  int nhlev = 0, nhlevf = 0, nhlevh = 0, nlevel = 0;
-  int nvct;
+  int nhlevf = 0, nhlevh = 0, nlevel = 0;
+  int nvct = 0;
   int psID = -1, lnpsID = -1, pvarID = -1;
   int code, param;
   char paramstr[32];
   char varname[CDI_MAX_NAME];
   double minval, maxval;
-  double *vct = NULL;
   double *ps_prog = NULL, *full_press = NULL, *half_press = NULL, *deltap = NULL;
   double *pout = NULL;
   double *pdata = NULL;
   int taxisID1, taxisID2;
-  int lhavevct;
   int nmiss;
-  int mono_level;
   int instNum, tableNum;
-  int useTable;
 
   cdoInitialize(argument);
 
@@ -79,114 +74,8 @@ void *Pressure(void *argument)
 
   int gridsize = vlist_check_gridsize(vlistID1);
 
-  nzaxis  = vlistNzaxis(vlistID1);
-  lhavevct = FALSE;
-  for ( i = 0; i < nzaxis; i++ )
-    {
-      mono_level = FALSE;
-      mono_level = TRUE;
-      zaxisID = vlistZaxis(vlistID1, i);
-      nlevel  = zaxisInqSize(zaxisID);
-
-      if ( (zaxisInqType(zaxisID) == ZAXIS_HYBRID || zaxisInqType(zaxisID) == ZAXIS_HYBRID_HALF) &&
-	   nlevel > 1 )
-	{
-	  double *level;
-	  int l;
-	  level = (double*) Malloc(nlevel*sizeof(double));
-	  zaxisInqLevels(zaxisID, level);
-	  for ( l = 0; l < nlevel; l++ )
-	    {
-	      if ( (l+1) != (int) (level[l]+0.5) ) break;
-	    }
-	  if ( l == nlevel ) mono_level = TRUE; 
-	  Free(level);
-	}
-
-      if ( (zaxisInqType(zaxisID) == ZAXIS_HYBRID || zaxisInqType(zaxisID) == ZAXIS_HYBRID_HALF) &&
-	   nlevel > 1 && mono_level )
-	{
-	  nvct = zaxisInqVctSize(zaxisID);
-	  if ( nlevel == (nvct/2 - 1) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  lhavevct = TRUE;
-		  zaxisIDh = zaxisID;
-		  nhlev    = nlevel;
-		  nhlevf   = nhlev;
-		  nhlevh   = nhlevf + 1;
-	      
-		  vct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID, vct);
-		}
-	    }
-	  else if ( nlevel == (nvct/2) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  lhavevct = TRUE;
-		  zaxisIDh = zaxisID;
-		  nhlev    = nlevel;
-		  nhlevf   = nhlev - 1;
-		  nhlevh   = nhlev;
-	      
-		  vct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID, vct);
-		}
-	    }
-	  else if ( nlevel == (nvct - 4 - 1) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  int vctsize;
-		  int voff = 4;
-		  double *rvct = NULL;
-
-		  rvct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID,rvct);
-
-		  if ( (int)(rvct[0]+0.5) == 100000 && rvct[voff] < rvct[voff+1] )
-		    {
-		      lhavevct = TRUE;
-		      zaxisIDh = zaxisID;
-		      nhlev    = nlevel;
-		      nhlevf   = nhlev;
-		      nhlevh   = nhlev + 1;
-
-		      vctsize = 2*nhlevh;
-		      vct = (double*) Malloc(vctsize*sizeof(double));
-
-		      /* calculate VCT for LM */
-
-		      for ( i = 0; i < vctsize/2; i++ )
-			{
-			  if ( rvct[voff+i] >= rvct[voff] && rvct[voff+i] <= rvct[3] )
-			    {
-			      vct[i] = rvct[0]*rvct[voff+i];
-			      vct[vctsize/2+i] = 0;
-			    }
-			  else
-			    {
-			      vct[i] = (rvct[0]*rvct[3]*(1-rvct[voff+i]))/(1-rvct[3]);
-			      vct[vctsize/2+i] = (rvct[voff+i]-rvct[3])/(1-rvct[3]);
-			    }
-			}
-		      
-		      if ( cdoVerbose )
-			{
-			  for ( i = 0; i < vctsize/2; i++ )
-			    fprintf(stdout, "%5d %25.17f %25.17f\n", i, vct[i], vct[vctsize/2+i]);
-			}
-		    }
-		  Free(rvct);
-		}
-	    }
-	}
-    }
-
-
-  nvars = vlistNvars(vlistID1);
+  int nhlev;
+  double *vct = vlist_read_vct(vlistID1, &zaxisIDh, &nvct, &nhlev, &nhlevf, &nhlevh);
 
   if ( zaxisIDh != -1 && gridsize > 0 )
     {
@@ -203,25 +92,23 @@ void *Pressure(void *argument)
   else
     zaxisIDp = zaxisCreate(ZAXIS_HYBRID_HALF, nhlevh);
 
-  {
-    double *level;
-    int l;
-    level = (double*) Malloc(nhlevh*sizeof(double));
-    for ( l = 0; l < nhlevh; l++ ) level[l] = l+1;
-    zaxisDefLevels(zaxisIDp, level);
-    Free(level);
-  }
+  double *level = (double*) Malloc(nhlevh*sizeof(double));
+  for ( int l = 0; l < nhlevh; l++ ) level[l] = l+1;
+  zaxisDefLevels(zaxisIDp, level);
+  Free(level);
 
   zaxisDefVct(zaxisIDp, 2*nhlevh, vct);
 
-  useTable = FALSE;
+  int nvars = vlistNvars(vlistID1);
+
+  bool useTable = false;
   for ( varID = 0; varID < nvars; varID++ )
     {
       tableNum = tableInqNum(vlistInqVarTable(vlistID1, varID));
 
       if ( tableNum > 0 && tableNum != 255 )
 	{
-	  useTable = TRUE;
+	  useTable = true;
 	  break;
 	}
     }
diff --git a/src/Remap.c b/src/Remap.c
index bf41b82..4fe0388 100644
--- a/src/Remap.c
+++ b/src/Remap.c
@@ -158,7 +158,7 @@ int maptype2operfunc(int map_type, int submap_type, int num_neighbors, int remap
   else
     cdoAbort("Unsupported mapping method (map_type = %d)", map_type);
 
-  return (operfunc);
+  return operfunc;
 } 
 
 static
@@ -257,9 +257,9 @@ int remap_test = 0;
 int remap_order = 1;
 int remap_non_global = FALSE;
 int remap_num_srch_bins = 180;
-int lremap_num_srch_bins = FALSE;
-int remap_extrapolate = FALSE;
-int lextrapolate = FALSE;
+static bool lremap_num_srch_bins = false;
+static bool remap_extrapolate = false;
+static bool lextrapolate = false;
 int max_remaps = -1;
 int sort_mode = HEAP_SORT;
 double remap_frac_min = 0;
@@ -420,7 +420,7 @@ void get_remap_env(void)
       if ( ival > 0 )
 	{
 	  remap_num_srch_bins = ival;
-	  lremap_num_srch_bins = TRUE;
+	  lremap_num_srch_bins = true;
 	  if ( cdoVerbose )
 	    cdoPrint("Set REMAP_NUM_SRCH_BINS to %d", remap_num_srch_bins);
 	}
@@ -463,22 +463,22 @@ void get_remap_env(void)
 	{
 	  if ( memcmp(envstr, "ON", 2) == 0 || memcmp(envstr, "on", 2) == 0 )
 	    {
-	      lextrapolate = TRUE;
-	      remap_extrapolate = TRUE;
+	      lextrapolate = true;
+	      remap_extrapolate = true;
 	    }
 	  else if ( memcmp(envstr, "OFF", 3) == 0 || memcmp(envstr, "off", 3) == 0 )
 	    {
-	      lextrapolate = TRUE;
-	      remap_extrapolate = FALSE;
+	      lextrapolate = true;
+	      remap_extrapolate = false;
 	    }
 	  else
 	    cdoWarning("Environment variable REMAP_EXTRAPOLATE has wrong value!");
 
 	  if ( cdoVerbose )
 	    {
-	      if ( remap_extrapolate == TRUE )
+	      if ( remap_extrapolate )
 		cdoPrint("Extrapolation enabled!");
-	      else if ( remap_extrapolate == FALSE )
+	      else
 		cdoPrint("Extrapolation disabled!");
 	    }
 	}
@@ -504,7 +504,7 @@ void get_remap_env(void)
 	    {
 	      if ( remap_genweights == TRUE )
 		cdoPrint("Generation of weights enabled!");
-	      else if ( remap_genweights == FALSE )
+	      else
 		cdoPrint("Generation of weights disabled!");
 	    }
 	}
@@ -514,23 +514,21 @@ void get_remap_env(void)
 static
 void set_halo_to_missval(int nx, int ny, double *array, double missval)
 {
-  int i, j;
-
-  for ( j = 0; j < ny+4; j++ ) array[j*(nx+4)+0]      = missval;
-  for ( j = 0; j < ny+4; j++ ) array[j*(nx+4)+1]      = missval;
-  for ( j = 0; j < ny+4; j++ ) array[j*(nx+4)+nx+2]   = missval;
-  for ( j = 0; j < ny+4; j++ ) array[j*(nx+4)+nx+3]   = missval;
-  for ( i = 0; i < nx+4; i++ ) array[     0*(nx+4)+i] = missval;
-  for ( i = 0; i < nx+4; i++ ) array[     1*(nx+4)+i] = missval;
-  for ( i = 0; i < nx+4; i++ ) array[(ny+2)*(nx+4)+i] = missval;
-  for ( i = 0; i < nx+4; i++ ) array[(ny+3)*(nx+4)+i] = missval;
+  for ( int j = 0; j < ny+4; j++ ) array[j*(nx+4)+0]      = missval;
+  for ( int j = 0; j < ny+4; j++ ) array[j*(nx+4)+1]      = missval;
+  for ( int j = 0; j < ny+4; j++ ) array[j*(nx+4)+nx+2]   = missval;
+  for ( int j = 0; j < ny+4; j++ ) array[j*(nx+4)+nx+3]   = missval;
+  for ( int i = 0; i < nx+4; i++ ) array[     0*(nx+4)+i] = missval;
+  for ( int i = 0; i < nx+4; i++ ) array[     1*(nx+4)+i] = missval;
+  for ( int i = 0; i < nx+4; i++ ) array[(ny+2)*(nx+4)+i] = missval;
+  for ( int i = 0; i < nx+4; i++ ) array[(ny+3)*(nx+4)+i] = missval;
 }
 
 static
-int is_global_grid(int gridID)
+bool is_global_grid(int gridID)
 {
-  int global_grid = TRUE;
-  int non_global = remap_non_global || !gridIsCircular(gridID);
+  bool global_grid = true;
+  bool non_global = remap_non_global || !gridIsCircular(gridID);
   int gridtype = gridInqType(gridID);
 
   if ( (gridtype == GRID_LONLAT && gridIsRotated(gridID)) ||
@@ -538,15 +536,15 @@ int is_global_grid(int gridID)
        (gridtype == GRID_LCC) ||
        (gridtype == GRID_LAEA) ||
        (gridtype == GRID_SINUSOIDAL) ||
-       (gridtype == GRID_CURVILINEAR && non_global) ) global_grid = FALSE;
+       (gridtype == GRID_CURVILINEAR && non_global) ) global_grid = false;
 
-  return (global_grid);
+  return global_grid;
 }
 
 static
 void scale_gridbox_area(long gridsize, const double *restrict array1, long gridsize2, double *restrict array2, const double *restrict grid2_area)
 {
-  static int lgridboxinfo = TRUE;
+  static bool lgridboxinfo = true;
   long i;
   double array1sum = 0;
   double array2sum = 0;
@@ -563,7 +561,7 @@ void scale_gridbox_area(long gridsize, const double *restrict array1, long grids
   if ( lgridboxinfo )
     {
       cdoPrint("gridbox_area replaced and scaled to %g", array1sum);
-      lgridboxinfo = FALSE;
+      lgridboxinfo = false;
     }
 }
 
@@ -595,10 +593,20 @@ int set_remapgrids(int filetype, int vlistID, int ngrids, int *remapgrids)
 	      else
 		cdoAbort("Unsupported grid type: %s, use CDO operator -setgridtype,regular to convert reduced to regular grid!", gridNamePtr(gridtype));
 	    }
-	  else if ( gridtype == GRID_GENERIC && gridInqSize(gridID) == 1 )
-	    remapgrids[index] = FALSE;
+	  else if ( gridtype == GRID_GENERIC && gridInqSize(gridID) <= 2 )
+            {
+              remapgrids[index] = FALSE;
+            }
 	  else
-	    cdoAbort("Unsupported grid type: %s", gridNamePtr(gridtype));
+            {
+              int nvars = vlistNvars(vlistID);
+              int varID;
+              for ( varID = 0; varID < nvars; ++varID )
+                if ( gridID == vlistInqVarGrid(vlistID, varID) ) break;
+              char varname[CDI_MAX_NAME];
+              vlistInqVarName(vlistID, varID, varname);
+              cdoAbort("Variable %s has an unsupported %s grid!", varname, gridNamePtr(gridtype));
+            }
 	}
     }
 
@@ -607,32 +615,30 @@ int set_remapgrids(int filetype, int vlistID, int ngrids, int *remapgrids)
 
   if ( index == ngrids ) cdoAbort("No remappable grid found!");
 
-  return (index);
+  return index;
 }
 
 static
 int set_max_remaps(int vlistID)
 {
   int max_remaps = 0;
-  int nzaxis, nvars, index;
-  int zaxisID, zaxissize;
 
-  nzaxis = vlistNzaxis(vlistID);
-  for ( index = 0; index < nzaxis; index++ )
+  const int nzaxis = vlistNzaxis(vlistID);
+  for ( int index = 0; index < nzaxis; index++ )
     {
-      zaxisID = vlistZaxis(vlistID, index);
-      zaxissize = zaxisInqSize(zaxisID);
+      const int zaxisID = vlistZaxis(vlistID, index);
+      const int zaxissize = zaxisInqSize(zaxisID);
       if ( zaxissize > max_remaps ) max_remaps = zaxissize;
     }
   
-  nvars = vlistNvars(vlistID);
+  const int nvars = vlistNvars(vlistID);
   if ( nvars > max_remaps ) max_remaps = nvars;
 
   max_remaps++;
 
   if ( cdoVerbose ) cdoPrint("Set max_remaps to %d", max_remaps);
 
-  return (max_remaps);
+  return max_remaps;
 }
 
 static
@@ -666,19 +672,18 @@ int get_norm_opt(void)
       else                                      cdoPrint("Normalization option: none");
     }
 
-  return (norm_opt);
+  return 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;
 
   if ( norm_opt == NORM_OPT_NONE )
     {
-      for ( i = 0; i < gridsize; i++ )
+      for ( int i = 0; i < gridsize; i++ )
 	{
 	  if ( !DBL_IS_EQUAL(array[i], missval) )
 	    {
@@ -693,7 +698,7 @@ void remap_normalize(int norm_opt, int gridsize, double *array, double missval,
     }
   else if ( norm_opt == NORM_OPT_DESTAREA )
     {
-      for ( i = 0; i < gridsize; i++ )
+      for ( int i = 0; i < gridsize; i++ )
 	{
 	  if ( !DBL_IS_EQUAL(array[i], missval) )
 	    {
@@ -817,18 +822,20 @@ void *Remap(void *argument)
 
   if ( operfunc == REMAPDIS || operfunc == GENDIS ||
        operfunc == REMAPNN  || operfunc == GENNN )
-    remap_extrapolate = TRUE;
+    remap_extrapolate = true;
 
   get_remap_env();
 
   if ( cdoVerbose )
     {
-      if ( remap_extrapolate == TRUE )
+      if ( remap_extrapolate )
 	cdoPrint("Extrapolation enabled!");
-      else if ( remap_extrapolate == FALSE )
+      else
 	cdoPrint("Extrapolation disabled!");
     }
 
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
   if ( lremapxxx )
     {
       operatorInputArg("grid description file or name, remap weights file (SCRIP NetCDF)");
@@ -855,7 +862,6 @@ void *Remap(void *argument)
 
   if ( gridInqType(gridID2) == GRID_GENERIC ) cdoAbort("Unsupported target grid type (generic)!");
 
-  int streamID1 = streamOpenRead(cdoStreamName(0));
   int filetype = streamInqFiletype(streamID1);
 
   int vlistID1 = streamInqVlist(streamID1);
@@ -902,13 +908,13 @@ void *Remap(void *argument)
       remaps[0].gridID   = gridID1;
       remaps[0].gridsize = gridInqSize(gridID1);
 
-      if ( map_type == MAP_TYPE_DISTWGT && !lextrapolate ) remap_extrapolate = TRUE;
-      if ( gridIsCircular(gridID1)      && !lextrapolate ) remap_extrapolate = TRUE;
+      if ( map_type == MAP_TYPE_DISTWGT && !lextrapolate ) remap_extrapolate = true;
+      if ( gridIsCircular(gridID1)      && !lextrapolate ) remap_extrapolate = true;
 
       if ( map_type == MAP_TYPE_DISTWGT && !remap_extrapolate && gridInqSize(gridID1) > 1 &&  !is_global_grid(gridID1) )
 	{
 	  remaps[0].gridsize += 4*(gridInqXsize(gridID1)+2) + 4*(gridInqYsize(gridID1)+2);
-	  remaps[0].src_grid.non_global = TRUE;
+	  remaps[0].src_grid.non_global = true;
 	}
 
       if ( gridInqType(gridID1) == GRID_GME ) gridsize = remaps[0].src_grid.nvgp;
@@ -1025,7 +1031,7 @@ void *Remap(void *argument)
 	  missval = vlistInqVarMissval(vlistID1, varID);
 	  gridsize = gridInqSize(gridID1);
 
-	  if ( gridIsCircular(gridID1) && !lextrapolate ) remap_extrapolate = TRUE;
+	  if ( gridIsCircular(gridID1) && !lextrapolate ) remap_extrapolate = true;
 	  if ( map_type == MAP_TYPE_DISTWGT && !remap_extrapolate && gridInqSize(gridID1) > 1 && !is_global_grid(gridID1) )
 	    {
 	      int gridsize_new;
@@ -1107,17 +1113,17 @@ void *Remap(void *argument)
 
 	      if ( remaps[r].gridID != gridID1 )
 		{
-		  if ( gridIsCircular(gridID1) && !lextrapolate ) remap_extrapolate = TRUE;
-		  remaps[r].src_grid.non_global = FALSE;
+		  if ( gridIsCircular(gridID1) && !lextrapolate ) remap_extrapolate = true;
+		  remaps[r].src_grid.non_global = false;
 		  if ( map_type == MAP_TYPE_DISTWGT && !remap_extrapolate && gridInqSize(gridID1) > 1 && !is_global_grid(gridID1) )
 		    {
-		      remaps[r].src_grid.non_global = TRUE;
+		      remaps[r].src_grid.non_global = true;
 		    }
 		  /*
 		    remaps[r].src_grid.luse_cell_area = FALSE;
 		    remaps[r].tgt_grid.luse_cell_area = FALSE;
 		  */
-		  if ( gridInqType(gridID1) != GRID_UNSTRUCTURED && lremap_num_srch_bins == FALSE )
+		  if ( gridInqType(gridID1) != GRID_UNSTRUCTURED && lremap_num_srch_bins == false )
 		    {
 		      if ( !remap_extrapolate && map_type == MAP_TYPE_DISTWGT )
 			{
diff --git a/src/Remapeta.c b/src/Remapeta.c
index 44f7d2c..93d9ab6 100644
--- a/src/Remapeta.c
+++ b/src/Remapeta.c
@@ -45,9 +45,7 @@ void setmissval(long nvals, int *imiss, double missval, double *array)
 static
 void corr_hum(long gridsize, double *q, double q_min)
 {
-  long i;
-
-  for ( i = 0; i < gridsize; ++i )
+  for ( long i = 0; i < gridsize; ++i )
     {
       if ( q[i] < q_min ) q[i] = q_min;
     }
@@ -92,7 +90,7 @@ long ncctop(double cptop, long nlev, long nlevp1, double *vct_a, double *vct_b)
       if ( zp[jk] >= cptop ) break;
     }
 
-  return (nctop);
+  return nctop;
 }
 
 
@@ -100,16 +98,12 @@ double *vctFromFile(const char *filename, int *nvct)
 {
   char line[1024], *pline;
   int num, i = 0;
-  int nlevh2, nvct2;
   int maxvct = 8192;
-  double *vct2;
-  FILE *fp;
-
 
-  fp = fopen(filename, "r");
+  FILE *fp = fopen(filename, "r");
   if ( fp == NULL ) { perror(filename); exit(EXIT_FAILURE); }
 
-  vct2 = (double*) Malloc(maxvct*sizeof(double));
+  double *vct2 = (double*) Malloc(maxvct*sizeof(double));
 
   while ( readline(fp, line, 1024) )
     {
@@ -132,8 +126,8 @@ double *vctFromFile(const char *filename, int *nvct)
 
   fclose(fp);
 
-  nvct2 = 2*i;
-  nlevh2 = i - 1;
+  int nvct2 = 2*i;
+  int nlevh2 = i - 1;
 
   for ( i = 0; i < nlevh2+1; ++i )
     vct2[i+nvct2/2] = vct2[i+maxvct/2];
@@ -142,7 +136,7 @@ double *vctFromFile(const char *filename, int *nvct)
 
   *nvct = nvct2;
 
-  return (vct2);
+  return vct2;
 }
 
 static
@@ -174,33 +168,68 @@ void vert_sumw(double *sum, double *var3d, long gridsize, long nlevel, double *d
 }
 
 
+double *vlist_hybrid_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlevf)
+{
+  int zaxisIDh = -1;
+  int nhlevf = 0;
+  int nvct = 0;
+  double *vct = NULL;
+
+  bool lhavevct = false;
+  int nzaxis = vlistNzaxis(vlistID);
+  for ( int i = 0; i < nzaxis; i++ )
+    {
+      int zaxisID = vlistZaxis(vlistID, i);
+      int nlevel  = zaxisInqSize(zaxisID);
+
+      if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID && nlevel > 1 )
+	{
+          nvct = zaxisInqVctSize(zaxisID);
+
+          if ( nlevel == (nvct/2 - 1) )
+            {
+	      if ( lhavevct == false )
+		{
+		  lhavevct = true;
+                  zaxisIDh = zaxisID;
+                  nhlevf  = nlevel;
+ 
+                  vct = (double*) Malloc(nvct*sizeof(double));
+                  zaxisInqVct(zaxisID, vct);
+                }
+            }
+          else 
+            {
+              if ( cdoVerbose )
+                cdoPrint("nlevel = (nvct1/2 - 1): nlevel = %d", nlevel);
+              if ( nlevel < (nvct/2 - 1) )
+                cdoPrint("z-axis %d has only %d of %d hybrid sigma pressure levels!", i+1, nlevel, (nvct/2 - 1));
+            }
+	}
+    }
+
+  *rzaxisIDh = zaxisIDh;
+  *rnvct   = nvct;
+  *rnhlevf = nhlevf;
+  
+  return vct;
+}
+
 #define  MAX_VARS3D  1024
 
 void *Remapeta(void *argument)
 {
-  int REMAPETA, REMAPETAS, REMAPETAZ;
-  int operatorID;
-  int streamID1, streamID2;
-  int vlistID1, vlistID2;
   int nfis2gp = 0;
   int recID, nrecs;
   int i, offset, iv;
-  int tsID, varID, levelID;
-  int nvars, nvars3D = 0;
-  int zaxisID2, zaxisIDh = -1, nzaxis, surfaceID;
-  int gridID, zaxisID;
+  int varID, levelID;
+  int nvars3D = 0;
+  int zaxisID;
   int nlevel;
-  int nvct1, nvct2 = 0;
   int sgeopotID = -1, tempID = -1, sqID = -1, psID = -1, lnpsID = -1, presID = -1;
   int code;
   char varname[CDI_MAX_NAME], stdname[CDI_MAX_NAME];
   double *single2;
-  int taxisID1, taxisID2;
-  int lhavevct;
-  int nhlevf1 = 0, nhlevf2 = 0;
-  double *lev2;
-  double *vct1 = NULL, *vct2 = NULL;
-  double *a1 = NULL, *b1 = NULL, *a2 = NULL, *b2 = NULL;
   double *fis1 = NULL, *ps1 = NULL, *t1 = NULL, *q1 = NULL;
   double *fis2 = NULL, *ps2 = NULL, *t2 = NULL, *q2 = NULL;
   double *tscor = NULL, *pscor = NULL, *secor = NULL;
@@ -220,22 +249,21 @@ void *Remapeta(void *argument)
   double missval = 0;
   double cconst = 1.E-6;
   const char *fname;
-  char *envstr;
   double cptop  = 0; /* min. pressure level for cond. */
 
   if ( cdoTimer ) timer_hetaeta = timer_new("Remapeta_hetaeta");
 
   cdoInitialize(argument);
 
-  REMAPETA  = cdoOperatorAdd("remapeta",   0, 0, "VCT file name");
-  REMAPETAS = cdoOperatorAdd("remapeta_s", 0, 0, "VCT file name");
-  REMAPETAZ = cdoOperatorAdd("remapeta_z", 0, 0, "VCT file name");
+  int REMAPETA  = cdoOperatorAdd("remapeta",   0, 0, "VCT file name");
+  int REMAPETAS = cdoOperatorAdd("remapeta_s", 0, 0, "VCT file name");
+  int REMAPETAZ = cdoOperatorAdd("remapeta_z", 0, 0, "VCT file name");
 
-  operatorID = cdoOperatorID();
+  int operatorID = cdoOperatorID();
 
   operatorInputArg(cdoOperatorEnter(operatorID));
 
-  envstr = getenv("REMAPETA_PTOP");
+  char *envstr = getenv("REMAPETA_PTOP");
   if ( envstr )
     {
       double fval = atof(envstr);
@@ -247,17 +275,18 @@ void *Remapeta(void *argument)
 	}
     }  
 
-  vct2 = vctFromFile(operatorArgv()[0], &nvct2);
-  nhlevf2 = nvct2/2 - 1;
+  int nvct2 = 0;
+  double *vct2 = vctFromFile(operatorArgv()[0], &nvct2);
+  int nhlevf2 = nvct2/2 - 1;
 
-  a2 = vct2;
-  b2 = vct2 + nvct2/2;
+  double *a2 = vct2;
+  double *b2 = vct2 + nvct2/2;
 
   if ( cdoVerbose )
     for ( i = 0; i < nhlevf2+1; ++i )
       cdoPrint("vct2: %5d %25.17f %25.17f", i, vct2[i], vct2[nvct2/2+i]);
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
   if ( operatorArgc() == 2 )
     {
@@ -270,10 +299,10 @@ void *Remapeta(void *argument)
       streamID = streamOpenRead(fileargument);
       file_argument_free(fileargument);
 
-      vlistID1 = streamInqVlist(streamID);
+      int vlistID1 = streamInqVlist(streamID);
 
       streamInqRecord(streamID, &varID, &levelID);
-      gridID  = vlistInqVarGrid(vlistID1, varID);
+      int gridID  = vlistInqVarGrid(vlistID1, varID);
       nfis2gp = gridInqSize(gridID);
 
       fis2 = (double*) Malloc(nfis2gp*sizeof(double));
@@ -283,7 +312,7 @@ void *Remapeta(void *argument)
       if ( nmiss )
 	{
 	  missval = vlistInqVarMissval(vlistID1, varID);
-	  imiss = (int*) malloc (nfis2gp*sizeof(int));
+	  imiss = (int*) Malloc(nfis2gp*sizeof(int));
 	  for ( i = 0; i < nfis2gp; ++i )
 	    {
 	      if ( DBL_IS_EQUAL(fis2[i], missval) )
@@ -306,21 +335,21 @@ void *Remapeta(void *argument)
       streamClose(streamID); 
     }
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  gridID = vlistGrid(vlistID1, 0);
+  int gridID = vlistGrid(vlistID1, 0);
   if ( gridInqType(gridID) == GRID_SPECTRAL )
     cdoAbort("Spectral data unsupported!");
 
   int gridsize = vlist_check_gridsize(vlistID1);
 
-  zaxisID2 = zaxisCreate(ZAXIS_HYBRID, nhlevf2);
-  lev2 = (double*) Malloc(nhlevf2*sizeof(double));
+  int zaxisID2 = zaxisCreate(ZAXIS_HYBRID, nhlevf2);
+  double *lev2 = (double*) Malloc(nhlevf2*sizeof(double));
   for ( i = 0; i < nhlevf2; ++i ) lev2[i] = i+1;
   zaxisDefLevels(zaxisID2, lev2);
   Free(lev2);
@@ -328,76 +357,32 @@ void *Remapeta(void *argument)
   if ( nvct2 == 0 ) cdoAbort("Internal problem, vct2 undefined!");
   zaxisDefVct(zaxisID2, nvct2, vct2);
 
-  surfaceID = zaxisFromName("surface");
+  int surfaceID = zaxisFromName("surface");
 
-  nzaxis  = vlistNzaxis(vlistID1);
-  lhavevct = FALSE;
+  int zaxisIDh = -1;
+  int nvct1 = 0;
+  int nhlevf1 = 0;
+  double *vct1 = vlist_hybrid_vct(vlistID1, &zaxisIDh, &nvct1, &nhlevf1);
 
-  if ( cdoVerbose )
-    cdoPrint("nzaxis: %d", nzaxis);
+  vlist_change_hybrid_zaxis(vlistID1, vlistID2, zaxisIDh, zaxisID2);
 
-  for ( i = 0; i < nzaxis; i++ )
+  int nzaxis = vlistNzaxis(vlistID1);
+  for ( int i = 0; i < nzaxis; i++ )
     {
-      zaxisID = vlistZaxis(vlistID1, i);
-      nlevel  = zaxisInqSize(zaxisID);
-      if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID )
-	{
-	  if ( nlevel > 1 )
-	    {
-	      nvct1 = zaxisInqVctSize(zaxisID);
-
-              if ( cdoVerbose )
-                cdoPrint("i: %d, vct1 size of zaxisID %d = %d", i, zaxisID, nvct1);
-
-	      if ( nlevel == (nvct1/2 - 1) )
-		{
-		  if ( lhavevct == FALSE )
-		    {
-		      lhavevct = TRUE;
-		      zaxisIDh = zaxisID;
-		      nhlevf1  = nlevel;
-	      
-                      if ( cdoVerbose )
-                        cdoPrint("lhavevct=TRUE  zaxisIDh = %d, nhlevf1   = %d", zaxisIDh, nlevel);
- 
-		      vct1 = (double*) Malloc(nvct1*sizeof(double));
-		      zaxisInqVct(zaxisID, vct1);
-		      
-		      vlistChangeZaxisIndex(vlistID2, i, zaxisID2);
-
-		      a1 = vct1;
-		      b1 = vct1 + nvct1/2;
-		      if ( cdoVerbose )
-			for ( i = 0; i < nvct1/2; ++i )
-			  cdoPrint("vct1: %5d %25.17f %25.17f", i, vct1[i], vct1[nvct1/2+i]);
-		    }
-		  else
-		    {
-		      if ( memcmp(vct1, zaxisInqVctPtr(zaxisID), nvct1*sizeof(double)) == 0 )
-			vlistChangeZaxisIndex(vlistID2, i, zaxisID2);
-		    }
-		}
-              else 
-                {
-		  if ( cdoVerbose )
-		    cdoPrint("nlevel = (nvct1/2 - 1): nlevel = %d", nlevel);
-		  if ( nlevel < (nvct1/2 - 1) )
-		    cdoPrint("z-axis %d has only %d of %d hybrid sigma pressure levels!", i+1, nlevel, (nvct1/2 - 1));
-                }
-	    }
-	  else
-	    {
-	      vlistChangeZaxisIndex(vlistID2, i, surfaceID);
-	    }
-	}
-      else
-        {
-	  if ( cdoVerbose )
-	    cdoPrint("i: %d, type of zaxisID %d not ZAXIS_HYBRID", i, zaxisID);
-        }
+      int zaxisID = vlistZaxis(vlistID1, i);
+      int nlevel  = zaxisInqSize(zaxisID);
+      if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID && nlevel == 1 )
+        vlistChangeZaxisIndex(vlistID2, i, surfaceID);
     }
+  
+  double *a1 = vct1;
+  double *b1 = vct1 + nvct1/2;
+  if ( cdoVerbose )
+    for ( i = 0; i < nvct1/2; ++i )
+      cdoPrint("vct1: %5d %25.17f %25.17f", i, vct1[i], vct1[nvct1/2+i]);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
@@ -405,7 +390,7 @@ void *Remapeta(void *argument)
   if ( zaxisIDh == -1 )
     cdoWarning("No 3D variable with hybrid sigma pressure coordinate found!");
 
-  nvars = vlistNvars(vlistID1);
+  int nvars = vlistNvars(vlistID1);
 
   for ( varID = 0; varID < nvars; varID++ )
     {
@@ -563,7 +548,7 @@ void *Remapeta(void *argument)
 
   if ( cdoVerbose ) cdoPrint("nvars3D = %d   ltq = %d", nvars3D, ltq);
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/SSOpar.c b/src/SSOpar.c
deleted file mode 100644
index d735501..0000000
--- a/src/SSOpar.c
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
-  This file is part of CDO. CDO is a collection of Operators to
-  manipulate and analyse Climate model Data.
-
-  Copyright (C) 2012-2012 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.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.
-*/
-
-/*
-   This module contains the following operators:
-
-      Derivepar     geopotheight          geopotential height
-*/
-
-#include <ctype.h>
-
-#include <cdi.h>
-#include "cdo.h"
-#include "cdo_int.h"
-#include "pstream.h"
-
-
-
-static
-void data_treat(double *zdata, double *xdata, double *ydata, long nx, long ny)
-{
-/*
-  PARAMETER(iwork=3000,jwork=1500)
-  REAL zdata(nx,ny),xdata(nx),ydata(ny)
-  REAL zwork(-iwork:2*iwork,jwork),xwork(-iwork:2*iwork)
-*/
-  double *zwork = NULL, *xwork = NULL;
-  double *xscale = NULL;
-  int *iscale = NULL;
-  long i, j;
-
-  zwork  = (double*) Malloc(3*nx*ny*sizeof(double));
-  xwork  = (double*) Malloc(3*nx*sizeof(double));
-  xscale = (double*) Malloc(ny*sizeof(double));
-  iscale = (int*) Malloc(ny*sizeof(int));
-
-  double pi2 = 2*acos(-1.);
-  for ( i = 0; i < nx; ++i )
-    {
-      xwork[i]      = xdata[i] - pi2;
-      xwork[i+nx]   = xdata[i];
-      xwork[i+nx*2] = xdata[i] + pi2;
-    }
-  /*
-  for ( j = 0; j < ny; ++j )
-    for ( i = 0; i < nx; ++i )
-      {
-	zwork(i   ,j)=zdata[j*nx+i];
-	zwork(i-nx,j)=zdata[j*nx+i];
-	zwork(i+nx,j)=zdata[j*nx+i];
-      }
-    }
-  */
-  /*
-  xincr=(xdata(2)-xdata(1))/2.
-  DO j=1,ny
-    xscale(j)=1./fabs(cos(ydata(j)))*xincr
-    !f77         iscale(j)=MIN(1./fabs(cos(ydata(j))),nx)
-    iscale(j)=1./fabs(cos(ydata(j)))
-    iscale(j)=MIN(iscale(j),nx)
-    !        print *,j,iscale(j)
-    DO i=1,nx
-      zdata(i,j)=0.
-      weight=0.
-      zlan=0.
-      ztot=0.
-      DO is=-iscale(j),iscale(j)
-        weig = MIN(2.*xincr,                                      &
-               MAX(xwork(i+is)+xincr-xwork[i]+xscale(j),0.),      &
-               MAX(xwork[i]+xscale(j)-xwork(i+is)+xincr,0.))
-        IF(weig > 0.)THEN
-          ztot=ztot+1.
-          IF(zwork(i+is,j) >= 1.)zlan=zlan+1.
-          weight=weight+weig
-          zdata(i,j)=zdata(i,j)+zwork(i+is,j)*weig
-        ENDIF
-      ENDDO
-      IF(zlan/ztot >= 0.5)THEN
-        zdata(i,j)=zdata(i,j)/weight
-      ELSE
-        zdata(i,j)=0.
-      ENDIF
-    ENDDO
-  ENDDO
-  */
-
-  Free(zwork);
-  Free(xwork);
-  Free(xscale);
-  Free(iscale);
-} // data_treat
-
-static
-void grid_noro(long imdep, long jmdep, double *xdata, double *ydata, double *zdata,          
-	       long imar, long jmar, double *x, double *y,                                   
-	       double *zphi, double *zmea, double *zstd, double *zsig, double *zgam, double *zthe,     
-	       double *zpic, double *zval, int *mask)
-{
-  /*
-  !=======================================================================
-  ! (F. Lott) (voir aussi z.x. Li, A. Harzallah et L. Fairhead)
-  !
-  !      Compute the Parameters of the SSO scheme as described in
-  !      LOTT & MILLER (1997) and LOTT(1999).
-  !      Target points are on a imarxjmar grid.
-  !      At the poles (if any) the fields value is repeated
-  !      jmar time.
-  !      The parameters a,b,c,d represent the limite of the target
-  !      gridpoint region. The means over this region are calculated
-  !      from USN data, ponderated by a weight proportional to the
-  !      surface occupated by the data inside the model gridpoint area.
-  !      In most circumstances, this weight is the ratio between the
-  !      surface of the USN gridpoint area and the surface of the
-  !      model gridpoint area.
-  !
-  !           (c)
-  !        ----d-----
-  !        | . . . .|
-  !        |        |
-  !     (b)a . * . .b(a)
-  !        |        |
-  !        | . . . .|
-  !        ----c-----
-  !           (d)
-  !=======================================================================
-  ! INPUT:
-  !        imdep, jmdep: dimensions X and Y input field
-  !        xdata, ydata: coordinates X and Y input field
-  !        zdata: Input field
-  !        In this version it is assumed that the entry data come from
-  !        the USNavy dataset: imdep=iusn=2160, jmdep=jusn=1080.
-  ! OUTPUT:
-  !        imar, jmar: dimensions X and Y Output field
-  !        x, y: ccordinates  X and Y Output field.
-  !             zmea:  Mean orographie
-  !             zstd:  Standard deviation
-  !             zsig:  Slope
-  !             zgam:  Anisotropy
-  !             zthe:  Orientation of the small axis
-  !             zpic:  Maximum altitude
-  !             zval:  Minimum altitude
-  !=======================================================================
-  */
-
-  // IMPLICIT INTEGER (i,j)
-  // IMPLICIT REAL(x,z)                                                
-
-  // PARAMETER(iext=216)
-  long iext = imdep/10;
-  /*
-  REAL xusn(imdep+2*iext),yusn(jmdep+2)	
-  REAL zusn(imdep+2*iext,jmdep+2)
-
-  REAL xdata(imdep),ydata(jmdep)
-  REAL zdata(imdep,jmdep)
-
-  ! INTERMEDIATE FIELDS  (CORRELATIONS OF OROGRAPHY GRADIENT)
-
-  REAL ztz(imar,jmar),zxtzx(imar,jmar)
-  REAL zytzy(imar,jmar),zxtzy(imar,jmar)
-  REAL weight(imar,jmar)
-  REAL num_tot(imar,jmar),num_lan(imar,jmar)
-
-  ! CORRELATIONS OF USN OROGRAPHY GRADIENTS
-
-  REAL zxtzxusn(imdep+2*iext,jmdep+2),zytzyusn(imdep+2*iext,jmdep+2)
-  REAL zxtzyusn(imdep+2*iext,jmdep+2)
-  REAL x(imar),y(jmar),zphi(imar,jmar)
-  ! INPUT FIELDS
-  REAL zmea(imar,jmar),zstd(imar,jmar)
-  REAL zsig(imar,jmar),zgam(imar,jmar),zthe(imar,jmar)
-  REAL zpic(imar,jmar),zval(imar,jmar)
-  INTEGER mask(imar,jmar)
-  !
-  REAL a(imar),b(imar),c(jmar),d(jmar)
-  INTEGER ia(imar),ib(imar),ic(jmar),id(jmar)
-  !
-  */
-
-  if ( cdoVerbose ) cdoPrint("Subgrid Scale Orography Parameters");
-
-  double xpi = acos(-1.);
-  double rad = 6371229.;
-  //  double zdeltay=2.*xpi/REAL(jmdep)*rad;
-
-  //  EXTENSION OF THE USN DATABASE TO POCEED COMPUTATIONS AT BOUNDARIES:
-
-  //data_treat(zdata, xdata, ydata, imdep, jmdep);
-
-  /*
-  DO j=1,jmdep
-    yusn(j+1)=ydata(j)
-    DO i=1,imdep
-      zusn(i+iext,j+1)=zdata(i,j)
-      xusn(i+iext)=xdata[i]
-    ENDDO
-    DO i=1,iext
-      zusn(i,j+1)=zdata(imdep-iext+i,j)
-      xusn[i]=xdata(imdep-iext+i)-2.*xpi
-      zusn(imdep+iext+i,j+1)=zdata(i,j)
-      xusn(imdep+iext+i)=xdata[i]+2.*xpi
-    ENDDO
-  ENDDO
-
-  yusn(1)=ydata(1)+(ydata(1)-ydata(2))
-  yusn(jmdep+2)=ydata(jmdep)+(ydata(jmdep)-ydata(jmdep-1))
-  DO i=1,imdep/2+iext
-    zusn(i,1)=zusn(i+imdep/2,2)
-    zusn(i+imdep/2+iext,1)=zusn(i,2)
-    zusn(i,jmdep+2)=zusn(i+imdep/2,jmdep+1)
-    zusn(i+imdep/2+iext,jmdep+2)=zusn(i,jmdep+1)
-  ENDDO
-  !
-  ! COMPUTE LIMITS OF MODEL GRIDPOINT AREA
-  !     ( REGULAR GRID)
-  !
-  a(1) = x(1) - (x(2)-x(1))/2.0
-  b(1) = (x(1)+x(2))/2.0
-  DO i = 2, imar-1
-    a[i] = b(i-1)
-    b[i] = (x[i]+x(i+1))/2.0
-  ENDDO
-  a(imar) = b(imar-1)
-  b(imar) = x(imar) + (x(imar)-x(imar-1))/2.0
-
-  IF(y(2) <= y(1))THEN
-    c(1) = y(1) - (y(2)-y(1))/2.0
-    d(1) = (y(1)+y(2))/2.0
-    DO j = 2, jmar-1
-      c(j) = d(j-1)
-      d(j) = (y(j)+y(j+1))/2.0
-    ENDDO
-    c(jmar) = d(jmar-1)
-    d(jmar) = y(jmar) + (y(jmar)-y(jmar-1))/2.0
-  ELSE
-    c(1) = (y(1)+y(2))/2.0
-    d(1) =  y(1) - (y(2)-y(1))/2.0
-    DO j = 2, jmar-1
-      d(j) = c(j-1)
-      c(j) = (y(j)+y(j+1))/2.0
-    ENDDO
-    d(jmar)=c(jmar-1)
-    c(jmar) = y(jmar) + (y(jmar)-y(jmar-1))/2.0
-  ENDIF
-
-  DO ii=1,imar
-    DO i=2,imdep+2*iext-1
-      IF(a(ii) >= xusn(i-1).AND.a(ii) < xusn[i])ia(ii)=i-1
-      IF(b(ii) > xusn[i].AND.b(ii) <= xusn(i+1))ib(ii)=i+1
-    ENDDO
-  ENDDO
-  DO jj=1,jmar
-    DO j=2,jmdep+1
-      IF(c(jj) >= yusn(j).AND.c(jj) < yusn(j-1))ic(jj)=j-1
-      IF(d(jj) > yusn(j+1).AND.d(jj) <= yusn(j))id(jj)=j+1
-    ENDDO
-  ENDDO
-
-  !
-  !  initialisations:
-  !
-  DO i = 1, imar
-    DO j = 1, jmar
-      weight(i,j) = 0.0
-      zxtzx(i,j)  = 0.0
-      zytzy(i,j)  = 0.0
-      zxtzy(i,j)  = 0.0
-      ztz(i,j)    = 0.0
-      zmea(i,j)   = 0.0
-      zpic(i,j)  =-1.e+10
-      zval(i,j)  = 1.e+10
-    ENDDO
-  ENDDO
-  !
-  !  COMPUTE SLOPES CORRELATIONS ON USN GRID
-  !
-  DO j = 1,jmdep+2
-    DO i = 1, imdep+2*iext
-      zytzyusn(i,j)=0.0
-      zxtzxusn(i,j)=0.0
-      zxtzyusn(i,j)=0.0
-    ENDDO
-  ENDDO
-
-
-  DO j = 2,jmdep+1
-    zdeltax=zdeltay*cos(yusn(j))
-    DO i = 2, imdep+2*iext-1
-      zytzyusn(i,j)=(zusn(i,j+1)-zusn(i,j-1))**2/zdeltay**2
-      zxtzxusn(i,j)=(zusn(i+1,j)-zusn(i-1,j))**2/zdeltax**2
-      zxtzyusn(i,j)=(zusn(i,j+1)-zusn(i,j-1))/zdeltay             &
-                   *(zusn(i+1,j)-zusn(i-1,j))/zdeltax
-    ENDDO
-  ENDDO
-  !
-  !  SUMMATION OVER GRIDPOINT AREA
-  !
-  zleny=xpi/REAL(jmdep)*rad
-  xincr=xpi/2./REAL(jmdep)
-  DO ii = 1, imar
-    DO jj = 1, jmar
-      num_tot(ii,jj)=0.
-      num_lan(ii,jj)=0.
-      !        PRINT *,' iteration ii jj:',ii,jj
-      DO j = ic(jj),id(jj)
-        zlenx=zleny*cos(yusn(j))
-        zdeltax=zdeltay*cos(yusn(j))
-        zbordnor=(c(jj)-yusn(j)+xincr)*rad
-        zbordsud=(yusn(j)-d(jj)+xincr)*rad
-        weighy=MAX(0.,MIN(zbordnor,zbordsud,zleny))
-        DO i = ia(ii),ib(ii)
-          zbordest=(xusn[i]-a(ii)+xincr)*rad*cos(yusn(j))
-          zbordoue=(b(ii)+xincr-xusn[i])*rad*cos(yusn(j))
-          weighx=MAX(0.,MIN(zbordest,zbordoue,zlenx))
-          num_tot(ii,jj)=num_tot(ii,jj)+1.0
-          IF(zusn(i,j) >= 1.)num_lan(ii,jj)=num_lan(ii,jj)+1.0
-          weight(ii,jj)=weight(ii,jj)+weighx*weighy
-          zxtzx(ii,jj)=zxtzx(ii,jj)+zxtzxusn(i,j)*weighx*weighy
-          zytzy(ii,jj)=zytzy(ii,jj)+zytzyusn(i,j)*weighx*weighy
-          zxtzy(ii,jj)=zxtzy(ii,jj)+zxtzyusn(i,j)*weighx*weighy
-          ztz(ii,jj)  =ztz(ii,jj)  +zusn(i,j)*zusn(i,j)*weighx*weighy
-          ! mean
-          zmea(ii,jj) =zmea(ii,jj)+zusn(i,j)*weighx*weighy
-          ! peacks
-          zpic(ii,jj)=MAX(zpic(ii,jj),zusn(i,j))
-          ! valleys
-          zval(ii,jj)=MIN(zval(ii,jj),zusn(i,j))
-        ENDDO
-      ENDDO
-    ENDDO
-  ENDDO
-  !
-  !  COMPUTE PARAMETERS NEEDED BY THE LOTT & MILLER (1997) AND
-  !  LOTT (1999) SSO SCHEME.
-  !
-  zllmmea=0.
-  zllmstd=0.
-  zllmsig=0.
-  zllmgam=0.
-  zllmpic=0.
-  zllmval=0.
-  zllmthe=0.
-  zminthe=0.
-  !     print 100,' '
-  !100  format(1X,A1,'II JJ',4X,'H',8X,'SD',8X,'SI',3X,'GA',3X,'TH')
-  DO ii = 1, imar
-    DO jj = 1, jmar
-      IF (weight(ii,jj)  /=  0.0) THEN
-        !  Mask
-        IF(num_lan(ii,jj)/num_tot(ii,jj) >= 0.5)THEN
-          mask(ii,jj)=1
-        ELSE
-          mask(ii,jj)=0
-        ENDIF
-        !  Mean Orography:
-        zmea (ii,jj)=zmea (ii,jj)/weight(ii,jj)
-        zxtzx(ii,jj)=zxtzx(ii,jj)/weight(ii,jj)
-        zytzy(ii,jj)=zytzy(ii,jj)/weight(ii,jj)
-        zxtzy(ii,jj)=zxtzy(ii,jj)/weight(ii,jj)
-        ztz(ii,jj)  =ztz(ii,jj)/weight(ii,jj)
-        !  Standard deviation:
-        zstd(ii,jj)=SQRT(MAX(0.,ztz(ii,jj)-zmea(ii,jj)**2))
-      ELSE
-        PRINT*, 'probleme,ii,jj=', ii,jj
-      ENDIF
-    ENDDO
-  ENDDO
-
-  ! CORRECT VALUES OF HORIZONTAL SLOPES NEAR THE POLES:
-
-  IF(y(jmar) <= -89.95.OR.y(jmar) >= 89.95)THEN
-
-    DO ii = 1, imar
-      zxtzx(ii,1)=zxtzx(ii,2)
-      zxtzx(ii,jmar)=zxtzx(ii,jmar-1)
-      zxtzy(ii,1)=zxtzy(ii,2)
-      zxtzy(ii,jmar)=zxtzy(ii,jmar-1)
-      zytzy(ii,1)=zytzy(ii,2)
-      zytzy(ii,jmar)=zytzy(ii,jmar-1)
-    ENDDO
-
-  ENDIF
-
-  !  FILTERS TO SMOOTH OUT FIELDS FOR INPUT INTO SSO SCHEME.
-
-  !  FIRST FILTER, MOVING AVERAGE OVER 9 POINTS.
-
-  CALL mva9(zmea,imar,jmar)
-  CALL mva9(zstd,imar,jmar)
-  CALL mva9(zpic,imar,jmar)
-  CALL mva9(zval,imar,jmar)
-  CALL mva9(zxtzx,imar,jmar)
-  CALL mva9(zxtzy,imar,jmar)
-  CALL mva9(zytzy,imar,jmar)
-
-  !  SECOND FILTER FOR SLOPES, MASK AND UNIFORM HORIS RESOLUTION
-
-  DO ii = 1, imar
-    DO jj = 1, jmar
-      zxtzx(ii,jj)=zxtzx(ii,jj)*mask(ii,jj)
-      zxtzy(ii,jj)=zxtzy(ii,jj)*mask(ii,jj)
-      zytzy(ii,jj)=zytzy(ii,jj)*mask(ii,jj)
-    ENDDO
-  ENDDO
-
-  CALL uni_res(zxtzx,y,imar,jmar)
-  CALL uni_res(zxtzy,y,imar,jmar)
-  CALL uni_res(zytzy,y,imar,jmar)
-
-
-  DO ii = 1, imar
-    DO jj = 1, jmar
-      IF (weight(ii,jj)  /=  0.0) THEN
-        !  Coefficients K, L et M:
-        xk=(zxtzx(ii,jj)+zytzy(ii,jj))/2.
-        xl=(zxtzx(ii,jj)-zytzy(ii,jj))/2.
-        xm=zxtzy(ii,jj)
-        xp=xk-SQRT(xl**2+xm**2)
-        xq=xk+SQRT(xl**2+xm**2)
-        xw=1.e-8
-        IF(xp <= xw) xp=0.
-        IF(xq <= xw) xq=xw
-        IF(fabs(xm) <= xw) xm=xw*SIGN(1.,xm)
-        ! slope:
-        zsig(ii,jj)=SQRT(xq)*mask(ii,jj)
-        ! isotropy:
-        zgam(ii,jj)=xp/xq*mask(ii,jj)
-        ! angle theta:
-        zthe(ii,jj)=57.29577951*ATAN2(xm,xl)/2.*mask(ii,jj)
-        zphi(ii,jj)=zmea(ii,jj)*mask(ii,jj)
-        zmea(ii,jj)=zmea(ii,jj)*mask(ii,jj)
-        zpic(ii,jj)=zpic(ii,jj)*mask(ii,jj)
-        zval(ii,jj)=zval(ii,jj)*mask(ii,jj)
-        zstd(ii,jj)=zstd(ii,jj)*mask(ii,jj)
-
-        !          print 101,ii,jj,
-        !    *           zmea(ii,jj),zstd(ii,jj),zsig(ii,jj),zgam(ii,jj),
-        !    *           zthe(ii,jj)
-        !101  format(1x,2(1x,i2),2(1x,f7.1),1x,f7.4,2x,f4.2,1x,f5.1)
-      ELSE
-        !           PRINT*, 'probleme,ii,jj=', ii,jj
-      ENDIF
-      zllmmea=MAX(zmea(ii,jj),zllmmea)
-      zllmstd=MAX(zstd(ii,jj),zllmstd)
-      zllmsig=MAX(zsig(ii,jj),zllmsig)
-      zllmgam=MAX(zgam(ii,jj),zllmgam)
-      zllmthe=MAX(zthe(ii,jj),zllmthe)
-      zminthe=MIN(zthe(ii,jj),zminthe)
-      zllmpic=MAX(zpic(ii,jj),zllmpic)
-      zllmval=MAX(zval(ii,jj),zllmval)
-    ENDDO
-  ENDDO
-
-  PRINT *,'  MEAN ORO:  ',zllmmea
-  PRINT *,'  ST. DEV.:  ',zllmstd
-  PRINT *,'  PENTE:     ',zllmsig
-  PRINT *,'  ANISOTROP: ',zllmgam
-  PRINT *,'  ANGLE:     ',zminthe,zllmthe	
-  PRINT *,'  pic:       ',zllmpic
-  PRINT *,'  val:       ',zllmval
-
-  ! ENSURE PERIODICITY AT HORIZONTAL GRID END
-
-  IF(xdata(imar) >= xdata(1)+2.*xpi-0.001)THEN
-    DO jj=1,jmar
-      zmea(imar,jj)=zmea(1,jj)
-      zpic(imar,jj)=zpic(1,jj)
-      zval(imar,jj)=zval(1,jj)
-      zstd(imar,jj)=zstd(1,jj)
-      zsig(imar,jj)=zsig(1,jj)
-      zgam(imar,jj)=zgam(1,jj)
-      zthe(imar,jj)=zthe(1,jj)
-    ENDDO
-  ENDIF
-
-  !
-  ! VALUES AT THE POLE (IF THERE ARE POLES
-  ! ON THE GRID CONSIDERED)
-  ! gamma and theta a 1. and 0. at poles
-  !
-  IF(ydata(1) <= -xpi/2+0.01.OR.ydata(1) >= xpi/2-0.01)THEN
-    zmeanor=0.0
-    zmeasud=0.0
-    zstdnor=0.0
-    zstdsud=0.0
-    zsignor=0.0
-    zsigsud=0.0
-    zweinor=0.0
-    zweisud=0.0
-    zpicnor=0.0
-    zpicsud=0.0
-    zvalnor=0.0
-    zvalsud=0.0
-
-    DO ii=1,imar
-      zweinor=zweinor+              weight(ii,   1)
-      zweisud=zweisud+              weight(ii,jmar)
-      zmeanor=zmeanor+zmea(ii,   1)*weight(ii,   1)
-      zmeasud=zmeasud+zmea(ii,jmar)*weight(ii,jmar)
-      zstdnor=zstdnor+zstd(ii,   1)*weight(ii,   1)
-      zstdsud=zstdsud+zstd(ii,jmar)*weight(ii,jmar)
-      zsignor=zsignor+zsig(ii,   1)*weight(ii,   1)
-      zsigsud=zsigsud+zsig(ii,jmar)*weight(ii,jmar)
-      zpicnor=zpicnor+zpic(ii,   1)*weight(ii,   1)
-      zpicsud=zpicsud+zpic(ii,jmar)*weight(ii,jmar)
-      zvalnor=zvalnor+zval(ii,   1)*weight(ii,   1)
-      zvalsud=zvalsud+zval(ii,jmar)*weight(ii,jmar)
-    ENDDO
-
-    DO ii=1,imar
-      zmea(ii,   1)=zmeanor/zweinor
-      zmea(ii,jmar)=zmeasud/zweisud
-      zphi(ii,   1)=zmeanor/zweinor
-      zphi(ii,jmar)=zmeasud/zweisud
-      zpic(ii,   1)=zpicnor/zweinor
-      zpic(ii,jmar)=zpicsud/zweisud
-      zval(ii,   1)=zvalnor/zweinor
-      zval(ii,jmar)=zvalsud/zweisud
-      zstd(ii,   1)=zstdnor/zweinor
-      zstd(ii,jmar)=zstdsud/zweisud
-      zsig(ii,   1)=zsignor/zweinor
-      zsig(ii,jmar)=zsigsud/zweisud
-      zgam(ii,   1)=1.
-      zgam(ii,jmar)=1.
-      zthe(ii,   1)=0.
-      zthe(ii,jmar)=0.
-    ENDDO
-
-  ENDIF
-  */
-} // grid_noro
-
-/*
-SUBROUTINE mva9(x,imar,jmar)
-
-  ! MAKE A MOVING AVERAGE OVER 9 GRIDPOINTS OF THE X FIELDS
-
-  REAL x(imar,jmar),xf(imar,jmar)
-  REAL weight(-1:1,-1:1)
-
-
-  sum=0.
-  DO is=-1,1
-    DO js=-1,1
-      weight(is,js)=1./REAL((1+is**2)*(1+js**2))
-      sum=sum+weight(is,js)
-    ENDDO
-  ENDDO
-
-  DO is=-1,1
-    DO js=-1,1
-      weight(is,js)=weight(is,js)/sum
-    ENDDO
-  ENDDO
-
-  DO j=2,jmar-1
-    DO i=2,imar-1
-      xf(i,j)=0.
-      DO is=-1,1
-        DO js=-1,1
-          xf(i,j)=xf(i,j)+x(i+is,j+js)*weight(is,js)
-        ENDDO
-      ENDDO
-    ENDDO
-  ENDDO
-
-  DO j=2,jmar-1
-    xf(1,j)=0.
-    is=imar-1
-    DO js=-1,1
-      xf(1,j)=xf(1,j)+x(is,j+js)*weight(-1,js)
-    ENDDO
-    DO is=0,1
-      DO js=-1,1
-        xf(1,j)=xf(1,j)+x(1+is,j+js)*weight(is,js)
-      ENDDO
-    ENDDO
-    xf(imar,j)=xf(1,j)
-  ENDDO
-
-  DO i=1,imar
-    xf(i,1)=xf(i,2)
-    xf(i,jmar)=xf(i,jmar-1)
-  ENDDO
-
-  DO i=1,imar
-    DO j=1,jmar
-      x(i,j)=xf(i,j)
-    ENDDO
-  ENDDO
-
-  RETURN
-END SUBROUTINE mva9
-
-SUBROUTINE uni_res(xfield,ylat,imar,jmar)
-
-  ! MAKE A MOVING AVERAGE OVER LONGITUDE POINTS
-  ! TO UNIFORMIZE THE HORIZONTAL RESOLUTION
-
-  REAL xfield(imar,jmar),xfilt(-imar:2*imar,jmar)
-  REAL ylat(jmar)
-
-
-  DO j=1,jmar
-    DO i=1,imar
-      xfilt(i+imar,j) = xfield(i,j)
-      xfilt(i-imar,j) = xfield(i,j)
-      xfilt(i     ,j) = xfield(i,j)
-    ENDDO
-  ENDDO
-
-  DO j=2,jmar-1
-    ism=1./cos(ylat(j))
-    !f77      ism=MIN(ism,imar-1)
-    ism=MIN(ism,imar-1)
-    DO i=1,imar
-      xfield(i,j)=0.
-      DO is=-ism,ism
-        xfield(i,j)=xfield(i,j)+xfilt(i+is,j)/REAL(2*ism+1)
-      ENDDO
-    ENDDO
-  ENDDO
-
-  !  POLES TREATMENT FOR SLOPES
-
-  IF(cos(ylat(1)) == 0)THEN
-    DO i=1,imar
-      xfield(i,1)   =0.
-      DO ii=1,imar
-        xfield(i,1)   =xfield(i,1)+xfilt(ii,1)/REAL(imar)
-      ENDDO
-    ENDDO
-  ELSE
-    ism=1./cos(ylat(1))
-    !f77        ism=MIN(ism,imar-1)
-    ism=MIN(ism,imar-1)
-    DO i=1,imar
-      xfield(i,1)   =0.
-      DO is=-ism,ism
-        xfield(i,1)=xfield(i,1)+xfilt(i+is,1)/REAL(2*ism+1)
-      ENDDO
-    ENDDO
-  ENDIF
-
-  IF(cos(ylat(jmar)) == 0)THEN
-    DO i=1,imar
-      xfield(i,jmar)=0.
-      DO ii=1,imar
-        xfield(i,jmar)=xfield(i,jmar)+xfilt(ii,jmar)/REAL(imar)
-      ENDDO
-    ENDDO
-  ELSE
-    ism=1./cos(ylat(jmar))
-    !f77        ism=MIN(ism,imar-1)
-    ism=MIN(ism,imar-1)
-    DO i=1,imar
-      xfield(i,jmar)   =0.
-      DO is=-ism,ism
-        xfield(i,jmar)=xfield(i,jmar)+xfilt(i+is,jmar)/REAL(2*ism+1)
-      ENDDO
-    ENDDO
-  ENDIF
-
-  RETURN
-END SUBROUTINE uni_res
-
-*/
-
-
-void *SSOpar(void *argument)
-{
-  int GEOPOTHEIGHT;
-  int operatorID;
-  int streamID1, streamID2;
-  int vlistID1, vlistID2;
-  int recID, nrecs;
-  int i, offset, iv;
-  int tsID, varID, levelID;
-  int nvars;
-  int zaxisID2, zaxisIDh = -1, nzaxis, surfaceID;
-  int zaxisID;
-  int nlevel;
-  int nvct;
-  int geopID = -1, tempID = -1, humID = -1, psID = -1, lnpsID = -1, presID = -1, clwcID = -1, ciwcID = -1;
-  int code;
-  char varname[CDI_MAX_NAME];
-  double *single2;
-  int taxisID1, taxisID2;
-  int lhavevct;
-  int nhlevf = 0;
-  double *lev2;
-  double *vct = NULL;
-  double *geop = NULL, *ps = NULL, *temp = NULL, *hum = NULL, *lwater = NULL, *iwater = NULL;
-  double *geopotheight = NULL;
-  int nmiss, nmissout = 0;
-  int ltq = FALSE;
-  double *array = NULL;
-  double *half_press = NULL;
-  double minval, maxval;
-  double missval = 0;
-  double cconst = 1.E-6;
-  const char *fname;
-
-
-  cdoInitialize(argument);
-
-  GEOPOTHEIGHT = cdoOperatorAdd("geopotheight",   0, 0, NULL);
-
-  operatorID = cdoOperatorID();
-
-
-  streamID1 = streamOpenRead(cdoStreamName(0));
-
-  vlistID1 = streamInqVlist(streamID1);
-
-  int gridID = vlistGrid(vlistID1, 0);
-  if ( gridInqType(gridID) == GRID_SPECTRAL )
-    cdoAbort("Spectral data unsupported!");
-
-  int gridsize = vlist_check_gridsize(vlistID1);
-
-  nzaxis  = vlistNzaxis(vlistID1);
-  lhavevct = FALSE;
-
-  if ( cdoVerbose )
-    cdoPrint("nzaxis: %d", nzaxis);
-
-  for ( i = 0; i < nzaxis; i++ )
-    {
-      zaxisID = vlistZaxis(vlistID1, i);
-      nlevel  = zaxisInqSize(zaxisID);
-      if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID )
-	{
-	  if ( nlevel > 1 )
-	    {
-	      nvct = zaxisInqVctSize(zaxisID);
-
-              if ( cdoVerbose )
-                cdoPrint("i: %d, vct size of zaxisID %d = %d", i, zaxisID, nvct);
-
-	      if ( nlevel == (nvct/2 - 1) )
-		{
-		  if ( lhavevct == FALSE )
-		    {
-		      lhavevct = TRUE;
-		      zaxisIDh = zaxisID;
-		      nhlevf   = nlevel;
-	      
-                      if ( cdoVerbose )
-                        cdoPrint("lhavevct=TRUE  zaxisIDh = %d, nhlevf   = %d", zaxisIDh, nlevel);
- 
-		      vct = (double*) Malloc(nvct*sizeof(double));
-		      zaxisInqVct(zaxisID, vct);
-
-		      if ( cdoVerbose )
-			for ( i = 0; i < nvct/2; ++i )
-			  cdoPrint("vct: %5d %25.17f %25.17f", i, vct[i], vct[nvct/2+i]);
-		    }
-		}
-              else 
-                {
-		  if ( cdoVerbose )
-		    cdoPrint("nlevel /= (nvct/2 - 1): nlevel = %d", nlevel);
-                }
-	    }
-	}
-    }
-
-  if ( zaxisIDh == -1 )
-    cdoAbort("No 3D variable with hybrid sigma pressure coordinate found!");
-
-  nvars = vlistNvars(vlistID1);
-
-  for ( varID = 0; varID < nvars; varID++ )
-    {
-      gridID  = vlistInqVarGrid(vlistID1, varID);
-      zaxisID = vlistInqVarZaxis(vlistID1, varID);
-      nlevel  = zaxisInqSize(zaxisID);
-
-      code = vlistInqVarCode(vlistID1, varID);
-      /* code = -1; */
-      if ( code <= 0 )
-	{
-	  vlistInqVarName(vlistID1, varID, varname);
-
-	  strtolower(varname);
-
-	  if ( nlevel == 1 )
-	    {
-	      if      ( strcmp(varname, "geosp")   == 0 ) code = 129;
-	      else if ( strcmp(varname, "aps")     == 0 ) code = 134;
-	      else if ( strcmp(varname, "ps")      == 0 ) code = 134;
-	      else if ( strcmp(varname, "lsp")     == 0 ) code = 152;
-	    }
-
-	  if ( nlevel == nhlevf )
-	    {
-	      if      ( strcmp(varname, "t")       == 0 ) code = 130;
-	      else if ( strcmp(varname, "q")       == 0 ) code = 133;
-	      else if ( strcmp(varname, "clwc")    == 0 ) code = 246;
-	      else if ( strcmp(varname, "ciwc")    == 0 ) code = 247;
-	    }
-	}
-
-      if      ( code == 129 ) geopID    = varID;
-      else if ( code == 130 ) tempID    = varID;
-      else if ( code == 133 ) humID     = varID;
-      else if ( code == 134 ) psID      = varID;
-      else if ( code == 152 ) lnpsID    = varID;
-      else if ( code == 246 ) clwcID    = varID;
-      else if ( code == 247 ) ciwcID    = varID;
-
-      if ( gridInqType(gridID) == GRID_SPECTRAL && zaxisInqType(zaxisID) == ZAXIS_HYBRID )
-	cdoAbort("Spectral data on model level unsupported!");
-
-      if ( gridInqType(gridID) == GRID_SPECTRAL )
-	cdoAbort("Spectral data unsupported!");
-
-
-      if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID && zaxisIDh != -1 && nlevel == nhlevf )
-	{
-	}
-      else
-	{
-	  if ( code == 130 ) tempID = -1;
-	  if ( code == 133 ) humID  = -1;
-	  if ( code == 246 ) clwcID  = -1;
-	  if ( code == 247 ) ciwcID  = -1;
-	}
-    }
-
-  if ( tempID == -1 ) cdoAbort("Temperature not found!");
-
-  array  = (double*) Malloc(gridsize*sizeof(double));
-
-  geop   = (double*) Malloc(gridsize*sizeof(double));
-  ps     = (double*) Malloc(gridsize*sizeof(double));
-
-  temp   = (double*) Malloc(gridsize*nhlevf*sizeof(double));
-  hum    = (double*) Malloc(gridsize*nhlevf*sizeof(double));
-  lwater = (double*) Malloc(gridsize*nhlevf*sizeof(double));
-  iwater = (double*) Malloc(gridsize*nhlevf*sizeof(double));
-
-  half_press   = (double*) Malloc(gridsize*(nhlevf+1)*sizeof(double));
-  geopotheight = (double*) Malloc(gridsize*(nhlevf+1)*sizeof(double));
-
-  if ( zaxisIDh != -1 && geopID == -1 )
-    {
-      if ( ltq )
-	cdoWarning("Orography (surf. geopotential) not found - set to zero!");
-
-      memset(geop, 0, gridsize*sizeof(double));
-    }
-
-  presID = lnpsID;
-  if ( zaxisIDh != -1 && lnpsID == -1 )
-    {
-      presID = psID;
-      if ( psID != -1 )
-	cdoWarning("LOG surface pressure (lsp) not found - using surface pressure (asp)!");
-      else
-	cdoAbort("Surface pressure not found!");
-    }
-
-
-  vlistID2 = vlistCreate();
-  varID = vlistDefVar(vlistID2, gridID, zaxisIDh, TSTEP_INSTANT);
-  vlistDefVarParam(vlistID2, varID, cdiEncodeParam(156, 128, 255));
-  vlistDefVarName(vlistID2, varID, "geopotheight");
-  vlistDefVarStdname(vlistID2, varID, "geopotential_height");
-  vlistDefVarUnits(vlistID2, varID, "m");
-
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
-  vlistDefTaxis(vlistID2, taxisID2);
-
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
-
-  streamDefVlist(streamID2, vlistID2);
-
-  tsID = 0;
-  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
-    {
-      taxisCopyTimestep(taxisID2, taxisID1);
-
-      streamDefTimestep(streamID2, tsID);
-
-      for ( recID = 0; recID < nrecs; recID++ )
-	{
-	  streamInqRecord(streamID1, &varID, &levelID);
-	  zaxisID  = vlistInqVarZaxis(vlistID1, varID);
-	  nlevel   = zaxisInqSize(zaxisID);
-	  offset   = gridsize*levelID;
-	  streamReadRecord(streamID1, array, &nmiss);
-
-	  if ( zaxisIDh != -1 )
-	    {
-	      if ( varID == geopID )
-		{
-		  memcpy(geop, array, gridsize*sizeof(double));
-		}
-	      else if ( varID == presID )
-		{
-		  if ( lnpsID != -1 )
-		    for ( i = 0; i < gridsize; ++i ) ps[i] = exp(array[i]);
-		  else if ( psID != -1 )
-		    memcpy(ps, array, gridsize*sizeof(double));
-		}
-	      else if ( varID == tempID )
-		memcpy(temp+offset, array, gridsize*sizeof(double));
-	      else if ( varID == humID )
-		memcpy(hum+offset, array, gridsize*sizeof(double));
-	      else if ( varID == clwcID )
-		memcpy(lwater+offset, array, gridsize*sizeof(double));
-	      else if ( varID == ciwcID )
-		memcpy(iwater+offset, array, gridsize*sizeof(double));
-	    }
-	}
-
-      if ( zaxisIDh != -1 )
-	{
-	  /* check range of ps_prog */
-
-	  minmaxval(gridsize, ps, NULL, &minval, &maxval);
-	  if ( minval < MIN_PS || maxval > MAX_PS )
-	    cdoWarning("Surface pressure out of range (min=%g max=%g)!", minval, maxval);
-
-	  /* check range of geop */
-
-	  minmaxval(gridsize, geop, NULL, &minval, &maxval);
-	  if ( minval < MIN_FIS || maxval > MAX_FIS )
-	    cdoWarning("Orography out of range (min=%g max=%g)!", minval, maxval);
-	}
-
-      varID = tempID;
-      nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
-      for ( levelID = 0; levelID < nlevel; levelID++ )
-	{
-	  offset   = gridsize*levelID;
-	  single2  = temp + offset;
-
-	  minmaxval(gridsize, single2, NULL, &minval, &maxval);
-	  if ( minval < MIN_T || maxval > MAX_T )
-	    cdoWarning("Input temperature at level %d out of range (min=%g max=%g)!",
-		       levelID+1, minval, maxval);
-	}
-
-
-      nmissout = 0;
-      varID = 0;
-      nlevel = nhlevf;
-      for ( levelID = 0; levelID < nlevel; levelID++ )
-	{
-	  streamDefRecord(streamID2, varID, levelID);
-	  streamWriteRecord(streamID2, geopotheight+levelID*gridsize, nmissout);
-	}
-
-      tsID++;
-    }
-
-  streamClose(streamID2);
-  streamClose(streamID1);
-
-  vlistDestroy(vlistID2);
-
-  Free(ps);
-  Free(geop);
-  Free(temp);
-  Free(geopotheight);
-  if ( hum ) Free(hum);
-
-  if ( half_press ) Free(half_press);
-
-  Free(array);
-  if ( vct ) Free(vct);
-
-  cdoFinish();
-
-  return 0;
-}
diff --git a/src/Select.c b/src/Select.c
index c10a32b..90e8f1d 100644
--- a/src/Select.c
+++ b/src/Select.c
@@ -27,455 +27,10 @@
 #include "pstream.h"
 #include "error.h"
 #include "util.h"
-//#include "list.h"
+#include "pmlist.h"
 
 double datestr_to_double(const char *datestr, int opt);
 
-#define  PML_INT         1
-#define  PML_FLT         2
-#define  PML_WORD        3
-#define  PML_DATE        4
-#define  PML_TIME        4
-
-/*
-typedef struct {
-  char *name;
-  int maxpar;
-  int numpar;
-  char *par;
-}
-PARAMETER;
-
-static PARAMETER Parameter[] =
-{
-  {"code", 1024, 0, NULL},
-};
-
-static int NumParameter = sizeof(Parameter) / sizeof(Parameter[0]);
-*/
-
-#define PML_DEF(name, size, txt)      bool flag_##name[size]; int npar_##name = 0; int max_##name = size; const char str_##name[] = txt
-#define PML_DEF_INT(name, size, txt)  int par_##name[size]; int name = 0; PML_DEF(name, size, txt)
-#define PML_DEF_FLT(name, size, txt)  double par_##name[size]; double name = 0; PML_DEF(name, size, txt)
-#define PML_DEF_WORD(name, size, txt) char *par_##name[size]; const char *name = 0; PML_DEF(name, size, txt)
-#define PML_INIT_INT(name)            memset(flag_##name, 0, max_##name * sizeof(bool))
-#define PML_INIT_FLT(name)            memset(flag_##name, 0, max_##name * sizeof(bool))
-#define PML_INIT_WORD(name)           memset(flag_##name, 0, max_##name * sizeof(bool))
-#define PML_ADD_INT(nml, name)        pmlAdd(nml, #name, PML_INT,  0, par_##name, sizeof(par_##name)/sizeof(int))
-#define PML_ADD_FLT(nml, name)        pmlAdd(nml, #name, PML_FLT,  0, par_##name, sizeof(par_##name)/sizeof(double))
-#define PML_ADD_WORD(nml, name)       pmlAdd(nml, #name, PML_WORD, 0, par_##name, sizeof(par_##name)/sizeof(char *))
-#define PML_NUM(nml, name)            npar_##name = pmlNum(nml, #name)
-#define PML_PAR(name)                 npar_##name, par_##name, name
-
-#define PAR_CHECK_INT_FLAG(name)      par_check_int_flag(npar_##name, par_##name, flag_##name, str_##name)
-#define PAR_CHECK_FLT_FLAG(name)      par_check_flt_flag(npar_##name, par_##name, flag_##name, str_##name)
-#define PAR_CHECK_WORD_FLAG(name)     par_check_word_flag(npar_##name, par_##name, flag_##name, str_##name)
-#define PAR_CHECK_INT(name)           par_check_int(npar_##name, par_##name, flag_##name, name)
-#define PAR_CHECK_FLT(name)           par_check_flt(npar_##name, par_##name, flag_##name, name)
-#define PAR_CHECK_WORD(name)          par_check_word(npar_##name, par_##name, flag_##name, name)
-#define PAR_CHECK_DATE(name)          par_check_date(npar_##name, par_##name, flag_##name, name)
-#define PAR_CHECK_SEASON(name, month) par_check_season(npar_##name, par_##name, flag_##name, month)
-
-#define MAX_PLIST_ENTRY  256
-#define MAX_PML_ENTRY    256
-
-typedef struct
-{
-  char *text;
-  size_t len;
-  void *ptr;
-  int type;
-  int occ;
-  int dis;
-  size_t size;
-} plist_entry_t;
-
-
-typedef struct
-{
-  int size;
-  plist_entry_t *entry[MAX_PLIST_ENTRY];
-} plist_t;
-
-
-typedef struct
-{
-  char *name;
-  size_t len;
-  void *ptr;
-  int type;
-  int occ;
-  int dis;
-  size_t size;
-} pml_entry_t;
-
-
-typedef struct
-{
-  int size;
-  int dis;
-  char *name;
-  /* PML_LINE line; */
-  pml_entry_t *entry[MAX_PML_ENTRY];
-} pml_t;
-
-
-static
-void pml_init(pml_t *pml, const char *name)
-{
-  pml->size = 0;
-  pml->dis  = 1;
-  pml->name = strdup(name);
-}
-
-
-pml_t *pmlNew(const char *name)
-{
-  pml_t *pml = (pml_t*) Malloc(sizeof(pml_t));
-
-  pml_init(pml, name);
-
-  return pml;
-}
-
-
-void pmlDestroy(pml_t *pml)
-{
-  if ( pml == NULL ) return;
-
-  for ( int i = 0; i < pml->size; ++i )
-    {
-      if ( pml->entry[i] ) Free(pml->entry[i]);
-    }
-
-  Free(pml);
-}
-
-
-void pmlPrint(pml_t *pml)
-{
-  pml_entry_t *entry;
-  int i, j, nout;
-
-  if ( pml == NULL ) return;
-
-  fprintf(stdout, "Parameter list: %s\n", pml->name);
-  fprintf(stdout, " Num  Name             Type  Size   Dis   Occ  Entries\n");
-
-  for ( i = 0; i < pml->size; ++i )
-    {
-      entry = pml->entry[i];
-      fprintf(stdout, "%4d  %-16s %4d  %4d  %4d  %4d ",
-	      i+1, pml->entry[i]->name, pml->entry[i]->type, (int)pml->entry[i]->size,
-	      pml->entry[i]->dis, pml->entry[i]->occ);
-      nout = pml->entry[i]->occ;
-      if ( nout > 8 ) nout = 8;
-
-      if      ( entry->type == PML_WORD )
-	for ( j = 0; j < nout; j++ )
-	  fprintf(stdout, " %s", ((char **)entry->ptr)[j]);
-      else if ( entry->type == PML_INT )
-	for ( j = 0; j < nout; j++ )
-	  fprintf(stdout, " %d", ((int *)entry->ptr)[j]);
-      else if ( entry->type == PML_FLT )
-	for ( j = 0; j < nout; j++ )
-	  fprintf(stdout, " %g", ((double *)entry->ptr)[j]);
-      
-      fprintf(stdout, "\n");
-    }
-}
-
-
-int pmlAdd(pml_t *pml, const char *name, int type, int dis, void *ptr, size_t size)
-{
-  if ( pml->size >= MAX_PML_ENTRY )
-    {
-      fprintf(stderr, "Too many entries in parameter list %s! (Max = %d)\n", pml->name, MAX_PML_ENTRY);
-      return -1;
-    }
-
-  pml_entry_t *pml_entry = (pml_entry_t*) Malloc(sizeof(pml_entry_t));
-
-  pml_entry->name = strdup(name);
-  pml_entry->len  = strlen(name);
-  pml_entry->type = type;
-  pml_entry->ptr  = ptr;
-  pml_entry->size = size;
-  pml_entry->dis  = dis;
-  pml_entry->occ  = 0;
-
-  int entry = pml->size;
-  pml->entry[pml->size++] = pml_entry;
-
-  return entry;
-}
-
-
-int pmlNum(pml_t *pml, const char *name)
-{
-  pml_entry_t *entry;
-  int i, nocc = 0;
-
-  if ( pml == NULL ) return (nocc);
-
-  for ( i = 0; i < pml->size; i++ )
-    {
-      entry = pml->entry[i];
-      if ( strcmp(name, entry->name) == 0 )
-	{
-	  nocc = entry->occ;
-	  break;
-	}
-    }
-
-  if ( i == pml->size )
-    fprintf(stderr, "Parameter list entry %s not found in %s\n", name, pml->name);
-
-  return nocc;
-}
-
-void split_intstring(const char *intstr, int *first, int *last, int *inc);
-
-int pml_add_entry(pml_entry_t *entry, char *arg)
-{
-  int status = 0;
-
-  if ( entry->type == PML_INT )
-    {
-      int ival, first, last, inc;
-
-      split_intstring(arg, &first, &last, &inc);
-
-      if ( inc >= 0 )
-	{
-	  for ( ival = first; ival <= last; ival += inc )
-	    if ( entry->occ < (int) entry->size )
-	      ((int *) entry->ptr)[entry->occ++] = ival;
-	}
-      else
-	{
-	  for ( ival = first; ival >= last; ival += inc )
-	    if ( entry->occ < (int) entry->size )
-	      ((int *) entry->ptr)[entry->occ++] = ival;
-	}
-    }
-  else if ( entry->type == PML_FLT )
-    {
-      if ( entry->occ < (int) entry->size )
-	((double *) entry->ptr)[entry->occ++] = atof(arg);
-    }
-  else if ( entry->type == PML_WORD )
-    {
-      if ( entry->occ < (int) entry->size )
-	((char **) entry->ptr)[entry->occ++] = strdupx(arg);
-    }
-  else
-    {
-      fprintf(stderr, "unsupported type!\n");
-    }
-
-  return status;
-}
-
-
-void pmlProcess(pml_entry_t *entry, int argc, char **argv)
-{
-  char *parg;
-  char *epos;
-
-  for ( int i = 0; i < argc; ++i )
-    {
-      parg = argv[i];
-      if ( i == 0 )
-	{
-	  epos = strchr(parg, '=');
-	  if ( epos == NULL )
-	    {
-	      fprintf(stderr, "internal problem, keyword not found!\n");
-	    }
-	  parg += epos-parg+1;
-	}
-
-      pml_add_entry(entry, parg);
-    }
-}
-
-
-int pmlRead(pml_t *pml, int argc, char **argv)
-{
-  pml_entry_t *entry = NULL;
-  pml_entry_t *pentry[MAX_PML_ENTRY];
-  int params[MAX_PML_ENTRY];
-  int num_par[MAX_PML_ENTRY];
-  int nparams = 0;
-  int i;
-  char *epos;
-  size_t len;
-  int bufsize = 0;
-  int status = 0;
-  /*
-  if ( cdoVerbose )
-    for ( i = 0; i < argc; ++i ) printf("pmlRead: %d %s\n", i, argv[i]);
-  */
-  for ( i = 0; i < argc; ++i )
-    {
-      len = strlen(argv[i]);
-      bufsize += len+1;
-    }
-
-  char *parbuf = (char*) Malloc(bufsize*sizeof(char));
-  memset(parbuf, 0, bufsize*sizeof(char));
-
-  int istart = 0;
-  while ( istart < argc )
-    {
-      epos = strchr(argv[istart], '=');
-      if ( epos == NULL )
-	{
-	  fprintf(stderr, "Parameter >%s< has no keyword!\n", argv[istart]);
-	  status = 1;
-	  goto END_LABEL;
-	}
-
-      len = epos - argv[istart];
-      for ( i = 0; i < pml->size; ++i )
-	{
-	  entry = pml->entry[i];
-	  if ( entry->len == len )
-	    if ( memcmp(entry->name, argv[istart], len) == 0 ) break;
-	}
-
-      if ( i == pml->size )
-	{
-	  fprintf(stderr, "Parameter >%s< has an invalid keyword!\n", argv[istart]);
-	  status = 2;
-	  goto END_LABEL;
-	}
-
-      num_par[nparams] = 0;
-      pentry[nparams]  = entry;
-      params[nparams]  = istart;
-      num_par[nparams] = 1;
-      
-      istart++;
-      for ( i = istart; i < argc; ++i )
-	{
-	  if ( *argv[i] == 0 ) { i++; break;}
-	  epos = strchr(argv[i], '=');
-	  if ( epos != NULL ) break;
-
-	  num_par[nparams]++;
-	}
-
-      istart = i;
-
-      nparams++;
-    }
-
-  for ( i = 0; i < nparams; ++i )
-    {
-      pmlProcess(pentry[i], num_par[i], &argv[params[i]]);
-    }
-
-
- END_LABEL:
-
-  Free(parbuf);
-
-  return status;
-}
-
-
-bool par_check_int(int npar, int *parlist, bool *flaglist, int par)
-{
-  bool found = false;
-  for ( int i = 0; i < npar; i++ )
-    if ( par == parlist[i] ) { found = true; flaglist[i] = true;/* break;*/}
-
-  return found;
-}
-
-
-bool par_check_flt(int npar, double *parlist, bool *flaglist, double par)
-{
-  bool found = false;
-  for ( int i = 0; i < npar; i++ )
-    if ( fabs(par - parlist[i]) < 1.e-4 ) { found = true; flaglist[i] = true;/* break;*/}
-
-  return found;
-}
-
-
-bool par_check_word(int npar, char **parlist, bool *flaglist, const char *par)
-{
-  bool found = false;
-  for ( int i = 0; i < npar; i++ )
-    if ( wildcardmatch(parlist[i], par) == 0 ) { found = true; flaglist[i] = true;/* break;*/}
-
-  return found;
-}
-
-
-bool par_check_date(int npar, char **parlist, bool *flaglist, const char *par)
-{
-  bool found = false;
-  char wcdate[512];
-
-  if ( *par == ' ' ) ++par;
-
-  for ( int i = 0; i < npar; i++ )
-    {
-      strcpy(wcdate, parlist[i]);
-      strcat(wcdate, "*");
-      if ( wildcardmatch(wcdate, par) == 0 ) { found = true; flaglist[i] = true;/* break;*/}
-    }
-
-  return found;
-}
-
-void season_to_months(const char *season, int *imonths);
-
-bool par_check_season(int npar, char **parlist, bool *flaglist, int month)
-{
-  assert(month>=1&&month<=12);
-  bool found = false;
-  int imon[13]; /* 1-12 ! */
-
-  for ( int i = 0; i < npar; i++ )
-    {
-      for ( int m = 0; m < 13; ++m ) imon[m] = 0;
-      season_to_months(parlist[i], imon);
-      if ( imon[month] ) { found = true; flaglist[i] = true;/* break;*/}
-    }
-
-  return found;
-}
-
-
-void par_check_int_flag(int npar, int *parlist, bool *flaglist, const char *txt)
-{
-  for ( int i = 0; i < npar; ++i )
-    if ( flaglist[i] == false )
-      cdoWarning("%s >%d< not found!", txt, parlist[i]);
-}
-
-
-void par_check_flt_flag(int npar, double *parlist, bool *flaglist, const char *txt)
-{
-  for ( int i = 0; i < npar; ++i )
-    if ( flaglist[i] == false )
-      cdoWarning("%s >%g< not found!", txt, parlist[i]);
-}
-
-
-void par_check_word_flag(int npar, char **parlist, bool *flaglist, const char *txt)
-{
-  for ( int i = 0; i < npar; ++i )
-    if ( flaglist[i] == false )
-      cdoWarning("%s >%s< not found!", txt, parlist[i]);
-}
-
-
 int vlist_get_psvarid(int vlistID, int zaxisID)
 {
   int psvarid = -1;
@@ -503,15 +58,40 @@ int vlist_get_psvarid(int vlistID, int zaxisID)
   return psvarid;
 }
 
+static
+void write_const_vars(int streamID2, int vlistID2, int nvars, double **vardata2)
+{
+  for ( int varID2c = 0; varID2c < nvars; ++varID2c )
+    {
+      if ( vardata2[varID2c] )
+        {
+          double missval = vlistInqVarMissval(vlistID2, varID2c);
+          int gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID2c));
+          int nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID2c));
+          for ( int levelID2c = 0; levelID2c < nlevel; ++levelID2c )
+            {
+              double *pdata = vardata2[varID2c]+gridsize*levelID2c;
+              int nmiss = 0;
+              for ( int i = 0; i < gridsize; ++i )
+                if ( DBL_IS_EQUAL(pdata[i], missval) ) nmiss++;
+
+              // if ( levelID2c == 0 ) printf("Write varID %d\n", varID2c);
+              streamDefRecord(streamID2, varID2c, levelID2c);
+              streamWriteRecord(streamID2, pdata, nmiss);
+            }
+          Free(vardata2[varID2c]);
+          vardata2[varID2c] = NULL;
+        }
+    }
+}  
+
 
 void *Select(void *argument)
 {
   bool lconstvars = true;
   int streamID2 = CDI_UNDEFID;
   int nrecs;
-  int nvars, nvars2, nlevs;
-  int zaxisID;
-  int varID2, levelID2;
+  int nvars, nvars2;
   int varID, levelID;
   int last_year = -999999999;
   char paramstr[32];
@@ -520,9 +100,8 @@ void *Select(void *argument)
   char gname[CDI_MAX_NAME];
   char zname[CDI_MAX_NAME];
   int vlistID0 = -1, vlistID2 = -1;
-  int result = FALSE;
   int taxisID2 = CDI_UNDEFID;
-  int ntsteps;
+  int ntsteps2 = 0;
   bool ltimsel = false;
   bool *vars = NULL;
   double **vardata2 = NULL;
@@ -530,59 +109,12 @@ void *Select(void *argument)
   double fstartdate = -99999999999.;
   double fenddate   = -99999999999.;
 
-  PML_DEF_INT(timestep_of_year, 4096, "Timestep of year");
-  PML_DEF_INT(timestep,         4096, "Timestep");
-  PML_DEF_INT(year,             1024, "Year");
-  PML_DEF_INT(month,              32, "Month");
-  PML_DEF_INT(day,                32, "Day");
-  PML_DEF_INT(hour,               24, "Hour");
-  PML_DEF_INT(minute,             60, "Minute");
-  PML_DEF_INT(code,             1024, "Code number");
-  PML_DEF_INT(levidx,           1024, "Level index");
-  PML_DEF_INT(ltype,             256, "Level type");
-  PML_DEF_INT(zaxisnum,          256, "Zaxis number");
-  PML_DEF_INT(gridnum,           256, "Grid number");
-  PML_DEF_FLT(level,            1024, "Level");
-  PML_DEF_WORD(name,            1024, "Variable name");
-  PML_DEF_WORD(param,           1024, "Parameter");
-  PML_DEF_WORD(zaxisname,        256, "Zaxis name");
-  PML_DEF_WORD(gridname,         256, "Grid name");
-  PML_DEF_WORD(steptype,          32, "Time step type");
-  PML_DEF_WORD(startdate,          1, "Start date");
-  PML_DEF_WORD(enddate,            1, "End date");
-  PML_DEF_WORD(season,            12, "Season");
-  PML_DEF_WORD(date,            1024, "Date");
-
-  PML_INIT_INT(timestep_of_year);
-  PML_INIT_INT(timestep);
-  PML_INIT_INT(year);
-  PML_INIT_INT(month);
-  PML_INIT_INT(day);
-  PML_INIT_INT(hour);
-  PML_INIT_INT(minute);
-  PML_INIT_INT(code);
-  PML_INIT_INT(levidx);
-  PML_INIT_INT(ltype);
-  PML_INIT_INT(zaxisnum);
-  PML_INIT_INT(gridnum);
-  PML_INIT_FLT(level);
-  PML_INIT_WORD(name);
-  PML_INIT_WORD(param);
-  PML_INIT_WORD(zaxisname);
-  PML_INIT_WORD(gridname);
-  PML_INIT_WORD(steptype);
-  PML_INIT_WORD(startdate);
-  PML_INIT_WORD(enddate);
-  PML_INIT_WORD(season);
-  PML_INIT_WORD(date);
-
   cdoInitialize(argument);
 
   int SELECT = cdoOperatorAdd("select", 0, 0, "parameter list");
   int DELETE = cdoOperatorAdd("delete", 0, 0, "parameter list");
 
-  bool lcopy = false;
-  if ( UNCHANGED_RECORD ) lcopy = true;
+  bool lcopy = UNCHANGED_RECORD;
 
   int operatorID = cdoOperatorID();
 
@@ -592,60 +124,37 @@ void *Select(void *argument)
   char **argnames = operatorArgv();
 
   if ( cdoVerbose )
-    for ( int i = 0; i < nsel; i++ )
-      printf("name %d = %s\n", i+1, argnames[i]);
-
-  pml_t *pml = pmlNew("SELECT");
-
-  PML_ADD_INT(pml, timestep_of_year);
-  PML_ADD_INT(pml, timestep);
-  PML_ADD_INT(pml, year);
-  PML_ADD_INT(pml, month);
-  PML_ADD_INT(pml, day);
-  PML_ADD_INT(pml, hour);
-  PML_ADD_INT(pml, minute);
-  PML_ADD_INT(pml, code);
-  PML_ADD_INT(pml, levidx);
-  PML_ADD_INT(pml, ltype);
-  PML_ADD_INT(pml, zaxisnum);
-  PML_ADD_INT(pml, gridnum);
-  PML_ADD_FLT(pml, level);
-  PML_ADD_WORD(pml, name);
-  PML_ADD_WORD(pml, param);
-  PML_ADD_WORD(pml, zaxisname);
-  PML_ADD_WORD(pml, gridname);
-  PML_ADD_WORD(pml, steptype);
-  PML_ADD_WORD(pml, startdate);
-  PML_ADD_WORD(pml, enddate);
-  PML_ADD_WORD(pml, season);
-  PML_ADD_WORD(pml, date);
-
-  pmlRead(pml, nsel, argnames);
-
-  if ( cdoVerbose ) pmlPrint(pml);
-
-  PML_NUM(pml, timestep_of_year);
-  PML_NUM(pml, timestep);
-  PML_NUM(pml, year);
-  PML_NUM(pml, month);
-  PML_NUM(pml, day);
-  PML_NUM(pml, hour);
-  PML_NUM(pml, minute);
-  PML_NUM(pml, code);
-  PML_NUM(pml, levidx);
-  PML_NUM(pml, ltype);
-  PML_NUM(pml, zaxisnum);
-  PML_NUM(pml, gridnum);
-  PML_NUM(pml, level);
-  PML_NUM(pml, name);
-  PML_NUM(pml, param);
-  PML_NUM(pml, zaxisname);
-  PML_NUM(pml, gridname);
-  PML_NUM(pml, steptype);
-  PML_NUM(pml, startdate);
-  PML_NUM(pml, enddate);
-  PML_NUM(pml, season);
-  PML_NUM(pml, date);
+    for ( int i = 0; i < nsel; ++i )
+      cdoPrint("name %d = %s", i+1, argnames[i]);
+
+  pml_t *pml = pml_create("SELECT");
+
+  PML_ADD_INT(pml, timestep_of_year, 4096, "Timestep of year");
+  PML_ADD_INT(pml, timestep,         4096, "Timestep");
+  PML_ADD_INT(pml, year,             1024, "Year");
+  PML_ADD_INT(pml, month,              32, "Month");
+  PML_ADD_INT(pml, day,                32, "Day");
+  PML_ADD_INT(pml, hour,               24, "Hour");
+  PML_ADD_INT(pml, minute,             60, "Minute");
+  PML_ADD_INT(pml, code,             1024, "Code number");
+  PML_ADD_INT(pml, levidx,           1024, "Level index");
+  PML_ADD_INT(pml, ltype,             256, "Level type");
+  PML_ADD_INT(pml, zaxisnum,          256, "Zaxis number");
+  PML_ADD_INT(pml, gridnum,           256, "Grid number");
+  PML_ADD_FLT(pml, level,            1024, "Level");
+  PML_ADD_WORD(pml, name,            1024, "Variable name");
+  PML_ADD_WORD(pml, param,           1024, "Parameter");
+  PML_ADD_WORD(pml, zaxisname,        256, "Zaxis name");
+  PML_ADD_WORD(pml, gridname,         256, "Grid name");
+  PML_ADD_WORD(pml, steptype,          32, "Time step type");
+  PML_ADD_WORD(pml, startdate,          1, "Start date");
+  PML_ADD_WORD(pml, enddate,            1, "End date");
+  PML_ADD_WORD(pml, season,            12, "Season");
+  PML_ADD_WORD(pml, date,            1024, "Date");
+
+  int status = pml_read(pml, nsel, argnames);
+  if ( cdoVerbose ) pml_print(pml);
+  if ( status != 0 ) cdoAbort("Parameter read error!");
 
   int streamCnt = cdoStreamCnt();
   int nfiles = streamCnt - 1;
@@ -654,7 +163,7 @@ void *Select(void *argument)
 
   timestep = 0;
   int tsID2 = 0;
-  for ( int indf = 0; indf < nfiles; indf++ )
+  for ( int indf = 0; indf < nfiles; ++indf )
     {
       if ( !cdoVerbose && nfiles > 1 ) progressStatus(0, 1, (indf+1.)/nfiles);
       if ( cdoVerbose ) cdoPrint("Process file: %s", cdoStreamName(indf)->args);
@@ -668,6 +177,8 @@ void *Select(void *argument)
 
       if ( indf == 0 )
 	{
+          bool xresult = false;
+
 	  // vlistID0 = vlistDuplicate(vlistID1);
 
 	  vlistClearFlag(vlistID1);
@@ -676,21 +187,30 @@ void *Select(void *argument)
 
 	  if ( operatorID == DELETE )
 	    {
-	      result = FALSE;
-	      for ( varID = 0; varID < nvars; varID++ )
+	      xresult = false;
+	      for ( varID = 0; varID < nvars; ++varID )
 		{
-		  zaxisID = vlistInqVarZaxis(vlistID1, varID);
-		  nlevs   = zaxisInqSize(zaxisID);
-		  for ( int levID = 0; levID < nlevs; levID++ )
+		  int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+		  int nlevs   = zaxisInqSize(zaxisID);
+		  for ( int levID = 0; levID < nlevs; ++levID )
 		    vlistDefFlag(vlistID1, varID, levID, TRUE);
 		}
 	    }
 	  else if ( operatorID == SELECT )
 	    {
-	      result = TRUE;
+	      xresult = true;
 	    }
 
-	  for ( varID = 0; varID < nvars; varID++ )
+          bool lvarsel = PML_NOCC(pml, code) || PML_NOCC(pml, ltype) || PML_NOCC(pml, zaxisnum) ||
+            PML_NOCC(pml, gridnum) || PML_NOCC(pml, name) || PML_NOCC(pml, param) ||
+            PML_NOCC(pml, zaxisname) || PML_NOCC(pml, gridname) || PML_NOCC(pml, steptype);
+          bool llevsel = PML_NOCC(pml, level) || PML_NOCC(pml, levidx);
+
+	  ltimsel = PML_NOCC(pml, date) || PML_NOCC(pml, startdate) || PML_NOCC(pml, enddate) || PML_NOCC(pml, season) ||
+            PML_NOCC(pml, timestep_of_year) || PML_NOCC(pml, timestep) || PML_NOCC(pml, year) || PML_NOCC(pml, month) ||
+            PML_NOCC(pml, day) || PML_NOCC(pml, hour) || PML_NOCC(pml, minute);
+          
+	  for ( varID = 0; varID < nvars; ++varID )
 	    {
 	      int iparam = vlistInqVarParam(vlistID1, varID);
 	      code = vlistInqVarCode(vlistID1, varID);
@@ -703,8 +223,8 @@ void *Select(void *argument)
 	      param = paramstr;
 
 	      int gridID  = vlistInqVarGrid(vlistID1, varID);
-	      zaxisID = vlistInqVarZaxis(vlistID1, varID);
-	      nlevs   = zaxisInqSize(zaxisID);
+	      int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+	      int nlevs   = zaxisInqSize(zaxisID);
 	      ltype   = zaxis2ltype(zaxisID);
 
               zaxisnum = vlistZaxisIndex(vlistID1, zaxisID)+1;
@@ -731,42 +251,43 @@ void *Select(void *argument)
               else                                    steptype = "unknown";
               
 	      vars[varID] = false;
-              bool found_code  = npar_code      && PAR_CHECK_INT(code);
-              bool found_name  = npar_name      && PAR_CHECK_WORD(name);
-              bool found_param = npar_param     && PAR_CHECK_WORD(param);
-              bool found_grid  = npar_gridnum   && PAR_CHECK_INT(gridnum);
-              bool found_gname = npar_gridname  && PAR_CHECK_WORD(gridname);
-              bool found_stype = npar_steptype  && PAR_CHECK_WORD(steptype);
-              bool found_ltype = npar_ltype     && PAR_CHECK_INT(ltype);
-              bool found_zaxis = npar_zaxisnum  && PAR_CHECK_INT(zaxisnum);
-              bool found_zname = npar_zaxisname && PAR_CHECK_WORD(zaxisname);
+              bool found_code  = PML_NOCC(pml, code)      && PML_CHECK_INT(pml, code);
+              bool found_name  = PML_NOCC(pml, name)      && PML_CHECK_WORD(pml, name);
+              bool found_param = PML_NOCC(pml, param)     && PML_CHECK_WORD(pml, param);
+              bool found_grid  = PML_NOCC(pml, gridnum)   && PML_CHECK_INT(pml, gridnum);
+              bool found_gname = PML_NOCC(pml, gridname)  && PML_CHECK_WORD(pml, gridname);
+              bool found_stype = PML_NOCC(pml, steptype)  && PML_CHECK_WORD(pml, steptype);
+              bool found_ltype = PML_NOCC(pml, ltype)     && PML_CHECK_INT(pml, ltype);
+              bool found_zaxis = PML_NOCC(pml, zaxisnum)  && PML_CHECK_INT(pml, zaxisnum);
+              bool found_zname = PML_NOCC(pml, zaxisname) && PML_CHECK_WORD(pml, zaxisname);
               bool lvar  = found_code || found_name || found_param;
-              bool lstep = npar_steptype ? found_stype : true;
-              bool lgrid = (npar_gridnum || npar_gridname) ? (found_grid || found_gname) : true;
-              bool lvert = (npar_ltype || npar_zaxisnum || npar_zaxisname) ? (found_ltype || found_zaxis || found_zname) : true;
-	      
-              if ( !vars[varID] && lgrid && lvar) vars[varID] = true;
-              if ( !vars[varID] && lvert && lvar) vars[varID] = true;
-              if ( !vars[varID] && lstep && lvar) vars[varID] = true;
+              bool lstep = PML_NOCC(pml, steptype) ? found_stype : true;
+              bool lgrid = (PML_NOCC(pml, gridnum) || PML_NOCC(pml, gridname)) ? (found_grid || found_gname) : true;
+              bool lvert = (PML_NOCC(pml, ltype) || PML_NOCC(pml, zaxisnum) || PML_NOCC(pml, zaxisname)) ? (found_ltype || found_zaxis || found_zname) : true;
+	     
+              if ( !vars[varID] && lgrid && lvar ) vars[varID] = true;
+              if ( !vars[varID] && lvert && lvar ) vars[varID] = true;
+              if ( !vars[varID] && lstep && lvar ) vars[varID] = true;
+
               if ( !vars[varID] && !lvar )
                 {
                   if      ( found_grid || found_gname ) vars[varID] = true;
                   else if ( found_stype ) vars[varID] = true;
                   else if ( found_ltype || found_zaxis || found_zname ) vars[varID] = true;
-                  else if ( npar_levidx || npar_level )
+                  else if ( !lvarsel && (PML_NOCC(pml, levidx) || PML_NOCC(pml, level)) )
                     {
-                      for ( int levID = 0; levID < nlevs; levID++ )
+                      for ( int levID = 0; levID < nlevs; ++levID )
                         {
                           levidx = levID + 1;
                           level = zaxisInqLevel(zaxisID, levID);
-                          if ( !vars[varID] && npar_levidx && PAR_CHECK_INT(levidx) )  vars[varID] = true;
-                          if ( !vars[varID] && npar_level  && PAR_CHECK_FLT(level)  )  vars[varID] = true;
+                          if ( !vars[varID] && PML_NOCC(pml, levidx) && PML_CHECK_INT(pml, levidx) ) vars[varID] = true;
+                          if ( !vars[varID] && PML_NOCC(pml, level)  && PML_CHECK_FLT(pml, level)  ) vars[varID] = true;
                         }
                     }
                 }
 	    }
 
-	  for ( varID = 0; varID < nvars; varID++ )
+	  for ( varID = 0; varID < nvars; ++varID )
 	    {
 	      if ( vars[varID] )
 		{
@@ -779,65 +300,61 @@ void *Select(void *argument)
                 }
             }
 
-	  for ( varID = 0; varID < nvars; varID++ )
+	  for ( varID = 0; varID < nvars; ++varID )
 	    {
 	      if ( vars[varID] )
 		{
-		  zaxisID = vlistInqVarZaxis(vlistID1, varID);
-		  nlevs   = zaxisInqSize(zaxisID);
-
-		  for ( int levID = 0; levID < nlevs; levID++ )
+		  int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+		  int nlevs   = zaxisInqSize(zaxisID);
+		  for ( int levID = 0; levID < nlevs; ++levID )
 		    {
 		      levidx = levID + 1;
 		      level = zaxisInqLevel(zaxisID, levID);
 		      
 		      if ( nlevs == 1 && IS_EQUAL(level, 0) )
 			{
-			  vlistDefFlag(vlistID1, varID, levID, result);
+			  vlistDefFlag(vlistID1, varID, levID, xresult);
 			}
 		      else
 			{
-			  if ( npar_levidx )
+			  if ( PML_NOCC(pml, levidx) )
 			    {
-			      if ( PAR_CHECK_INT(levidx) )
-				vlistDefFlag(vlistID1, varID, levID, result);
+			      if ( PML_CHECK_INT(pml, levidx) )
+				vlistDefFlag(vlistID1, varID, levID, xresult);
 			    }
-			  else if ( npar_level )
+			  else if ( PML_NOCC(pml, level) )
 			    {
-			      if ( PAR_CHECK_FLT(level) )
-				vlistDefFlag(vlistID1, varID, levID, result);
+			      if ( PML_CHECK_FLT(pml, level) )
+				vlistDefFlag(vlistID1, varID, levID, xresult);
 			    }
 			  else
 			    {
-			      vlistDefFlag(vlistID1, varID, levID, result);
+			      vlistDefFlag(vlistID1, varID, levID, xresult);
 			    }
 			}
 		    }
 		}
 	    }
 
-	  PAR_CHECK_INT_FLAG(code);
-	  PAR_CHECK_INT_FLAG(levidx);
-	  PAR_CHECK_INT_FLAG(ltype);
-	  PAR_CHECK_INT_FLAG(zaxisnum);
-	  PAR_CHECK_INT_FLAG(gridnum);
-	  PAR_CHECK_FLT_FLAG(level);
-	  PAR_CHECK_WORD_FLAG(name);
-	  PAR_CHECK_WORD_FLAG(param);
-	  PAR_CHECK_WORD_FLAG(zaxisname);
-	  PAR_CHECK_WORD_FLAG(gridname);
-	  PAR_CHECK_WORD_FLAG(steptype);
-
-	  if ( npar_date || npar_startdate || npar_enddate || npar_season ) ltimsel = true;
-	  if ( npar_timestep_of_year || npar_timestep || npar_year || npar_month || npar_day || npar_hour || npar_minute ) ltimsel = true;
+	  PML_CHECK_INT_FLAG(pml, code);
+	  PML_CHECK_INT_FLAG(pml, levidx);
+	  PML_CHECK_INT_FLAG(pml, ltype);
+	  PML_CHECK_INT_FLAG(pml, zaxisnum);
+	  PML_CHECK_INT_FLAG(pml, gridnum);
+	  PML_CHECK_FLT_FLAG(pml, level);
+	  PML_CHECK_WORD_FLAG(pml, name);
+	  PML_CHECK_WORD_FLAG(pml, param);
+	  PML_CHECK_WORD_FLAG(pml, zaxisname);
+	  PML_CHECK_WORD_FLAG(pml, gridname);
+	  PML_CHECK_WORD_FLAG(pml, steptype);
 
 	  int npar = 0;
-	  for ( varID = 0; varID < nvars; varID++ )
+	  for ( varID = 0; varID < nvars; ++varID )
 	    {
-	      zaxisID = vlistInqVarZaxis(vlistID1, varID);
-	      nlevs   = zaxisInqSize(zaxisID);
-	      for ( int levID = 0; levID < nlevs; levID++ )
-		if ( vlistInqFlag(vlistID1, varID, levID) == result )
+	      int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+	      int nlevs   = zaxisInqSize(zaxisID);
+	      for ( int levID = 0; levID < nlevs; ++levID )
+		if ( vlistInqFlag(vlistID1, varID, levID) == TRUE )
                   {
                     npar++;
                     break;
@@ -846,16 +363,16 @@ void *Select(void *argument)
 
 	  if ( npar == 0 )
 	    {
-	      if ( ltimsel == true )
+	      if ( (! lvarsel) && (! llevsel) && ltimsel )
 		{
                   lcopy_const = true;
 
-		  for ( varID = 0; varID < nvars; varID++ )
+		  for ( varID = 0; varID < nvars; ++varID )
 		    {
 		      vars[varID] = true;
-		      zaxisID = vlistInqVarZaxis(vlistID1, varID);
-		      nlevs   = zaxisInqSize(zaxisID);
-		      for ( int levID = 0; levID < nlevs; levID++ )
+		      int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+		      int nlevs   = zaxisInqSize(zaxisID);
+		      for ( int levID = 0; levID < nlevs; ++levID )
 			vlistDefFlag(vlistID1, varID, levID, TRUE);
 		    }
 		}
@@ -864,15 +381,29 @@ void *Select(void *argument)
 		  cdoAbort("No variable selected!");
 		}
 	    }
+          else
+            {
+              if ( lvarsel && ltimsel )
+                {
+                  for ( varID = 0; varID < nvars; ++varID )
+                    {
+                      if ( vars[varID] == true && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
+                        {
+                          lcopy_const = true;
+                          break;
+                        }
+                    }
+                }
+            }
 
 	  //if ( cdoVerbose ) vlistPrint(vlistID1);
 
 	  vlistID0 = vlistDuplicate(vlistID1);
-	  for ( varID = 0; varID < nvars; varID++ )
+	  for ( varID = 0; varID < nvars; ++varID )
 	    {
-	      zaxisID = vlistInqVarZaxis(vlistID1, varID);
-	      nlevs   = zaxisInqSize(zaxisID);
-	      for ( int levID = 0; levID < nlevs; levID++ )
+	      int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+	      int nlevs   = zaxisInqSize(zaxisID);
+	      for ( int levID = 0; levID < nlevs; ++levID )
 		vlistDefFlag(vlistID0, varID, levID, vlistInqFlag(vlistID1, varID, levID));
 	    }
 
@@ -886,7 +417,7 @@ void *Select(void *argument)
 	  taxisID2 = taxisDuplicate(taxisID1);
 	  vlistDefTaxis(vlistID2, taxisID2);
 
-	  ntsteps = vlistNtsteps(vlistID1);
+	  int ntsteps = vlistNtsteps(vlistID1);
 
 	  nvars2 = vlistNvars(vlistID2);
 
@@ -898,11 +429,9 @@ void *Select(void *argument)
 	      if ( varID == nvars2 ) ntsteps = 0;
 	    }
 
-	  int ntsteps2 = ntsteps;
-	  if ( operatorID == SELECT && npar_timestep == 1 ) ntsteps2 = 1;
+	  ntsteps2 = ntsteps;
+	  if ( operatorID == SELECT && PML_NOCC(pml, timestep) == 1 ) ntsteps2 = 1;
 	  
-	  if ( ntsteps2 == 0 || ntsteps2 == 1 ) vlistDefNtsteps(vlistID2, ntsteps2);
-
 	  if ( ntsteps2 == 0 && nfiles > 1 )
 	    {
               lconstvars = false;
@@ -911,14 +440,14 @@ void *Select(void *argument)
 	    }
 
 	  // support for negative timestep values
-	  if ( npar_timestep > 0 && ntsteps > 0 && nfiles == 1 )
+	  if ( PML_NOCC(pml, timestep) > 0 && ntsteps > 0 && nfiles == 1 )
 	    {
-	      for ( int i = 0; i < npar_timestep; i++ )
+	      for ( int i = 0; i < PML_NOCC(pml, timestep); ++i )
 		{
 		  if ( par_timestep[i] < 0 )
 		    {
 		      if ( cdoVerbose )
-			cdoPrint("timestep %d changed to %d", par_timestep[i], par_timestep[i] + ntsteps + 1 );
+			cdoPrint("timestep %d changed to %d", par_timestep[i], par_timestep[i] + ntsteps + 1);
 		      par_timestep[i] += ntsteps + 1;
 		    }
 		}
@@ -933,8 +462,8 @@ void *Select(void *argument)
 
 	  startdate = par_startdate[0];
 	  enddate   = par_enddate[0];
-	  if ( npar_startdate ) fstartdate = datestr_to_double(startdate, 0);
-	  if ( npar_enddate   ) fenddate   = datestr_to_double(enddate, 1);
+	  if ( PML_NOCC(pml, startdate) ) fstartdate = datestr_to_double(startdate, 0);
+	  if ( PML_NOCC(pml, enddate)   ) fenddate   = datestr_to_double(enddate, 1);
 	}
       else
 	{
@@ -950,7 +479,7 @@ void *Select(void *argument)
 
       if ( lcopy_const )
         {
-          vardata2 = (double**) malloc(nvars2*sizeof(double));
+          vardata2 = (double**) Malloc(nvars2*sizeof(double));
           for ( varID = 0; varID < nvars2; ++varID ) vardata2[varID] = NULL;
         }
 
@@ -965,7 +494,7 @@ void *Select(void *argument)
 	    {
 	      copytimestep = false;
 
-	      if ( operatorID == SELECT && npar_timestep > 0 && timestep > par_timestep[npar_timestep-1] )
+	      if ( operatorID == SELECT && PML_NOCC(pml, timestep) > 0 && timestep > par_timestep[PML_NOCC(pml, timestep)-1] )
 		{
 		  lstop = true;
 		  break;
@@ -986,26 +515,26 @@ void *Select(void *argument)
 
 	      timestep_of_year++;
 
-	      if ( npar_timestep && PAR_CHECK_INT(timestep) ) copytimestep = true;
-	      if ( npar_timestep_of_year && PAR_CHECK_INT(timestep_of_year) ) copytimestep = true;
+	      if ( PML_NOCC(pml, timestep) && PML_CHECK_INT(pml, timestep) ) copytimestep = true;
+	      if ( PML_NOCC(pml, timestep_of_year) && PML_CHECK_INT(pml, timestep_of_year) ) copytimestep = true;
 
-	      if ( !copytimestep && npar_date == 0 && npar_timestep == 0 && npar_timestep_of_year == 0 )
+	      if ( !copytimestep && PML_NOCC(pml, date) == 0 && PML_NOCC(pml, timestep) == 0 && PML_NOCC(pml, timestep_of_year) == 0 )
 		{
 		  bool lseason = false, lyear = false, lmonth = false, lday = false, lhour = false, lminute = false;
 
-		  if ( npar_season == 0 || (npar_season && PAR_CHECK_SEASON(season, month)) ) lseason   = true;
-		  if ( npar_year   == 0 || (npar_year   && PAR_CHECK_INT(year))   ) lyear   = true;
-		  if ( npar_month  == 0 || (npar_month  && PAR_CHECK_INT(month))  ) lmonth  = true;
-		  if ( npar_day    == 0 || (npar_day    && PAR_CHECK_INT(day))    ) lday    = true;
-		  if ( npar_hour   == 0 || (npar_hour   && PAR_CHECK_INT(hour))   ) lhour   = true;
-		  if ( npar_minute == 0 || (npar_minute && PAR_CHECK_INT(minute)) ) lminute = true;
+		  if ( PML_NOCC(pml, season) == 0 || (PML_NOCC(pml, season) && PML_CHECK_SEASON(pml, season, month)) ) lseason   = true;
+		  if ( PML_NOCC(pml, year)   == 0 || (PML_NOCC(pml, year)   && PML_CHECK_INT(pml, year))   ) lyear   = true;
+		  if ( PML_NOCC(pml, month)  == 0 || (PML_NOCC(pml, month)  && PML_CHECK_INT(pml, month))  ) lmonth  = true;
+		  if ( PML_NOCC(pml, day)    == 0 || (PML_NOCC(pml, day)    && PML_CHECK_INT(pml, day))    ) lday    = true;
+		  if ( PML_NOCC(pml, hour)   == 0 || (PML_NOCC(pml, hour)   && PML_CHECK_INT(pml, hour))   ) lhour   = true;
+		  if ( PML_NOCC(pml, minute) == 0 || (PML_NOCC(pml, minute) && PML_CHECK_INT(pml, minute)) ) lminute = true;
 
 		  if ( lseason && lyear && lmonth && lday && lhour && lminute ) copytimestep = true;
 		}
 
 	      double fdate = ((double)vdate) + ((double)vtime)/1000000.;
 
-	      if ( npar_enddate )
+	      if ( PML_NOCC(pml, enddate) )
 		{
 		  if ( fdate > fenddate )
 		    {
@@ -1023,7 +552,7 @@ void *Select(void *argument)
 		    }
 		}
 
-	      if ( npar_startdate )
+	      if ( PML_NOCC(pml, startdate) )
 		{
 		  if ( fdate < fstartdate )
 		    {
@@ -1037,12 +566,12 @@ void *Select(void *argument)
 		}
 
               
-              if ( npar_date )
+              if ( PML_NOCC(pml, date) )
                 {
                   char vdatetimestr[64];
                   datetime2str(vdate, vtime, vdatetimestr, sizeof(vdatetimestr));
                   date = vdatetimestr;
-                  if ( PAR_CHECK_DATE(date) ) copytimestep = true;
+                  if ( PML_CHECK_DATE(pml, date) ) copytimestep = true;
                 }
 
 	      if ( operatorID == DELETE ) copytimestep = !copytimestep;
@@ -1054,37 +583,17 @@ void *Select(void *argument)
 	    {
 	      if ( streamID2 == CDI_UNDEFID )
 		{
+                  bool lasttimestep = (nfiles == 1) && (ntsteps2 > 1) && (ntsteps2 == (tsID1+1));
+                  if ( lasttimestep && tsID2 == 0 ) ntsteps2 = 1;
+                  if ( ntsteps2 == 0 || ntsteps2 == 1 ) vlistDefNtsteps(vlistID2, ntsteps2);
 		  streamID2 = streamOpenWrite(cdoStreamName(nfiles), cdoFiletype());
 		  streamDefVlist(streamID2, vlistID2);
 		}
 
 	      taxisCopyTimestep(taxisID2, taxisID1);
 	      streamDefTimestep(streamID2, tsID2);
-
-              if ( lcopy_const && tsID2 == 0 )
-                {
-                  for ( varID2 = 0; varID2 < nvars2; ++varID2 )
-                    {
-                      if ( vardata2[varID2] )
-                        {
-                          double missval = vlistInqVarMissval(vlistID2, varID2);
-                          int gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID2));
-                          int nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID2));
-                          for ( int levelID2 = 0; levelID2 < nlevel; ++levelID2 )
-                            {
-                              double *pdata = vardata2[varID2]+gridsize*levelID;
-                              int nmiss = 0;
-                              for ( int i = 0; i < gridsize; ++i )
-                                if ( DBL_IS_EQUAL(pdata[i], missval) ) nmiss++;
-
-                              streamDefRecord(streamID2, varID2, levelID2);
-                              streamWriteRecord(streamID2, pdata, nmiss);
-                            }
-                        }
-                    }
-                }
               
-	      for ( int recID = 0; recID < nrecs; recID++ )
+	      for ( int recID = 0; recID < nrecs; ++recID )
 		{
 		  streamInqRecord(streamID1, &varID, &levelID);
 		  if ( vlistInqFlag(vlistID0, varID, levelID) == TRUE )
@@ -1093,10 +602,14 @@ void *Select(void *argument)
                         if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
                           continue;
 
-		      varID2   = vlistFindVar(vlistID2, varID);
-		      levelID2 = vlistFindLevel(vlistID2, varID, levelID);
+		      int varID2   = vlistFindVar(vlistID2, varID);
+		      int levelID2 = vlistFindLevel(vlistID2, varID, levelID);
 		      
-		      streamDefRecord(streamID2, varID2, levelID2);
+                      if ( lcopy_const && tsID2 == 0 )
+                        write_const_vars(streamID2, vlistID2, varID2, vardata2);
+
+                      streamDefRecord(streamID2, varID2, levelID2);
+                      // if ( levelID2 == 0 ) printf("Write varID %d\n", varID2);
 		      if ( lcopy )
 			{
 			  streamCopyRecord(streamID2, streamID1);
@@ -1110,27 +623,30 @@ void *Select(void *argument)
 		    }
 		}
 
+              if ( lcopy_const && tsID2 == 0 )
+                write_const_vars(streamID2, vlistID2, nvars2, vardata2);
+
 	      tsID2++;              
 	    }
           else if ( lcopy_const && indf == 0 && tsID1 == 0 )
             {
-	      for ( int recID = 0; recID < nrecs; recID++ )
+	      for ( int recID = 0; recID < nrecs; ++recID )
 		{
 		  streamInqRecord(streamID1, &varID, &levelID);
 		  if ( vlistInqFlag(vlistID0, varID, levelID) == TRUE )
 		    {
-		      varID2 = vlistFindVar(vlistID2, varID);
+		      int varID2 = vlistFindVar(vlistID2, varID);
                       if ( vlistInqVarTsteptype(vlistID2, varID2) == TSTEP_CONSTANT )
                         {
-                          levelID2 = vlistFindLevel(vlistID2, varID, levelID);
+                          int levelID2 = vlistFindLevel(vlistID2, varID, levelID);
                           int gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID2));
                           if ( levelID == 0 )
                             {
                               int nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID2));
-                              vardata2[varID2] = (double*) malloc(gridsize*nlevel*sizeof(double));
+                              vardata2[varID2] = (double*) Malloc(gridsize*nlevel*sizeof(double));
                             }
                           int nmiss;
-                          streamReadRecord(streamID1, vardata2[varID2]+gridsize*levelID, &nmiss);
+                          streamReadRecord(streamID1, vardata2[varID2]+gridsize*levelID2, &nmiss);
                         }
 		    }
 		}
@@ -1148,34 +664,33 @@ void *Select(void *argument)
 
   if ( !cdoVerbose && nfiles > 1 ) progressStatus(0, 1, 1);    
 
-  PAR_CHECK_INT_FLAG(timestep_of_year);
-  PAR_CHECK_INT_FLAG(timestep);
-  PAR_CHECK_INT_FLAG(year);
-  PAR_CHECK_INT_FLAG(month);
-  PAR_CHECK_INT_FLAG(day);
-  PAR_CHECK_INT_FLAG(hour);
-  PAR_CHECK_INT_FLAG(minute);
-  PAR_CHECK_WORD_FLAG(startdate);
-  UNUSED(str_enddate);
-  //  PAR_CHECK_WORD_FLAG(enddate);
-  PAR_CHECK_WORD_FLAG(season);
-  PAR_CHECK_WORD_FLAG(date);
+  PML_CHECK_INT_FLAG(pml, timestep_of_year);
+  PML_CHECK_INT_FLAG(pml, timestep);
+  PML_CHECK_INT_FLAG(pml, year);
+  PML_CHECK_INT_FLAG(pml, month);
+  PML_CHECK_INT_FLAG(pml, day);
+  PML_CHECK_INT_FLAG(pml, hour);
+  PML_CHECK_INT_FLAG(pml, minute);
+  PML_CHECK_WORD_FLAG(pml, startdate);
+  //  PML_CHECK_WORD_FLAG(pml, enddate);
+  PML_CHECK_WORD_FLAG(pml, season);
+  PML_CHECK_WORD_FLAG(pml, date);
 
   if ( streamID2 != CDI_UNDEFID ) streamClose(streamID2);
 
   vlistDestroy(vlistID0);
   vlistDestroy(vlistID2);
 
-  pmlDestroy(pml);
+  pml_destroy(pml);
 
   if ( array ) Free(array);
   if ( vars ) Free(vars);
   if ( vardata2 )
     {
-      for ( varID = 0; varID < nvars2; ++ varID )
-        if ( vardata2[varID] ) free(vardata2[varID]);
+      for ( varID = 0; varID < nvars2; ++varID )
+        if ( vardata2[varID] ) Free(vardata2[varID]);
 
-      free(vardata2);
+      Free(vardata2);
     }
 
   if ( tsID2 == 0 ) cdoAbort("No timesteps selected!");
diff --git a/src/Seloperator.c b/src/Seloperator.c
index bc871d2..65fbfdc 100644
--- a/src/Seloperator.c
+++ b/src/Seloperator.c
@@ -23,38 +23,33 @@
 
 void *Seloperator(void *argument)
 {
-  int streamID1, streamID2 = CDI_UNDEFID;
   int nrecs;
-  int tsID, recID, varID, levelID;
-  int vlistID1, vlistID2;
-  int taxisID1, taxisID2;
-  int scode, sltype;
+  int recID, varID, levelID;
   double slevel = 0, level;
-  int nvars, nlevs, code, zaxisID, selfound = FALSE;
+  int nlevs, code, zaxisID, selfound = FALSE;
   int levID, ltype = 0;
   int varID2, levelID2;
   int sellevel, selcode, selltype;
-  int lcopy = FALSE;
   int gridsize, nmiss;
   double *array = NULL;
 
   cdoInitialize(argument);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
   operatorInputArg("code, ltype, level");
 
-  scode  = parameter2int(operatorArgv()[0]);
-  sltype = parameter2int(operatorArgv()[1]);
+  int scode  = parameter2int(operatorArgv()[0]);
+  int sltype = parameter2int(operatorArgv()[1]);
 
   if ( operatorArgc() == 3 )
     slevel = parameter2double(operatorArgv()[2]);
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
+  int vlistID1 = streamInqVlist(streamID1);
 
-  nvars = vlistNvars(vlistID1);
+  int nvars = vlistNvars(vlistID1);
   for ( varID = 0; varID < nvars; varID++ )
     {
       code    = vlistInqVarCode(vlistID1, varID);
@@ -93,14 +88,14 @@ void *Seloperator(void *argument)
   if ( selfound == FALSE )
     cdoWarning("Code %d, ltype %d, level %g not found!", scode, sltype, slevel);
 
-  vlistID2 = vlistCreate();
+  int vlistID2 = vlistCreate();
   vlistCopyFlag(vlistID2, vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
@@ -110,7 +105,7 @@ void *Seloperator(void *argument)
       array = (double*) Malloc(gridsize*sizeof(double));
     }
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Seltime.c b/src/Seltime.c
index 30fd852..cd7516a 100644
--- a/src/Seltime.c
+++ b/src/Seltime.c
@@ -172,16 +172,11 @@ void *Seltime(void *argument)
 {
   int streamID2 = -1;
   int nrecs;
-  int recID, varID, levelID;
-  int nsel = 0, selival;
-  int vdate, vtime;
-  int copytimestep;
-  int copy_nts2 = FALSE;
-  int i, isel;
-  int gridsize;
+  int varID, levelID;
+  int nsel = 0;
+  int i;
   int nmiss;
   int ncts = 0, nts, it;
-  int *selfound = NULL;
   int hour = 0, minute = 0, second = 0;
   int nts1 = 0, nts2 = 0;
   int its1 = 0, its2 = 0;
@@ -189,16 +184,18 @@ void *Seltime(void *argument)
   double *array = NULL;
   LIST *ilist = listNew(INT_LIST);
   LIST *flist = listNew(FLT_LIST);
-  int gridID;
-  int nlevel;
-  int lconstout = FALSE;
-  int process_nts1 = FALSE, process_nts2 = FALSE;
+  bool copy_nts2 = false;
+  bool lconstout = false;
+  bool process_nts1 = false, process_nts2 = false;
+  bool *selfound = NULL;
   int *vdate_list = NULL, *vtime_list = NULL;
   double *single;
   field_t ***vars = NULL;
 
   cdoInitialize(argument);
 
+  bool lcopy = UNCHANGED_RECORD;
+
   int SELTIMESTEP = cdoOperatorAdd("seltimestep", func_step,     0, "timesteps");
   int SELDATE     = cdoOperatorAdd("seldate",     func_datetime, 0, "start date and end date (format YYYY-MM-DDThh:mm:ss)");
   int SELTIME     = cdoOperatorAdd("seltime",     func_time,     0, "times (format hh:mm:ss)");
@@ -213,9 +210,6 @@ void *Seltime(void *argument)
 
   int operfunc = cdoOperatorF1(operatorID);
 
-  int lcopy = FALSE;
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
-
   operatorInputArg(cdoOperatorEnter(operatorID));
 
   if ( operatorID == SELSEASON )
@@ -269,8 +263,8 @@ void *Seltime(void *argument)
 
   if ( nsel )
     {
-      selfound = (int*) Malloc(nsel*sizeof(int));
-      for ( i = 0; i < nsel; i++ ) selfound[i] = FALSE;
+      selfound = (bool*) Malloc(nsel*sizeof(bool));
+      for ( i = 0; i < nsel; i++ ) selfound[i] = false;
     }
 
   int streamID1 = streamOpenRead(cdoStreamName(0));
@@ -287,7 +281,7 @@ void *Seltime(void *argument)
 
   if ( ! lcopy )
     {
-      gridsize = vlistGridsizeMax(vlistID1);
+      int gridsize = vlistGridsizeMax(vlistID1);
       if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
       array = (double*) Malloc(gridsize*sizeof(double));
     }
@@ -322,7 +316,7 @@ void *Seltime(void *argument)
   for ( varID = 0; varID < nvars; varID++ )
     if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) nconst++;
       
-  int lnts1 = operatorID == SELSMON && nts1 > 0;
+  bool lnts1 = (operatorID == SELSMON) && (nts1 > 0);
 
   if ( lnts1 || nconst )
     {
@@ -346,9 +340,9 @@ void *Seltime(void *argument)
 	    {
 	      if ( lnts1 || (vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT) )
 		{
-		  gridID  = vlistInqVarGrid(vlistID1, varID);
-		  nlevel  = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
-		  gridsize = gridInqSize(gridID);
+		  int gridID  = vlistInqVarGrid(vlistID1, varID);
+		  int nlevel  = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
+		  int gridsize = gridInqSize(gridID);
 		  
 		  for ( levelID = 0; levelID < nlevel; levelID++ )
 		    {
@@ -363,11 +357,11 @@ void *Seltime(void *argument)
   int tsID2 = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
-      vdate = taxisInqVdate(taxisID1);
-      vtime = taxisInqVtime(taxisID1);
+      int vdate = taxisInqVdate(taxisID1);
+      int vtime = taxisInqVtime(taxisID1);
 
-      copytimestep = FALSE;
-      selival = -1;
+      bool copytimestep = false;
+      int selival = -1;
 
       if ( operfunc == func_step )
 	{
@@ -398,9 +392,9 @@ void *Seltime(void *argument)
 	{
 	  if ( selfval >= fltarr[0] && selfval <= fltarr[nsel-1] )
 	    {
-	      copytimestep = TRUE;
-	      selfound[0]      = TRUE;
-	      selfound[nsel-1] = TRUE;
+	      copytimestep = true;
+	      selfound[0]      = true;
+	      selfound[nsel-1] = true;
 	    }
           else if ( selfval > fltarr[nsel-1] )
             {
@@ -412,29 +406,29 @@ void *Seltime(void *argument)
 	  for ( i = 0; i < nsel; i++ )
 	    if ( selival == intarr[i] )
 	      {
-		copytimestep = TRUE;
-		selfound[i] = TRUE;
+		copytimestep = true;
+		selfound[i] = true;
 		break;
 	      }
 	}
 
-      if ( operatorID == SELSMON && copytimestep == FALSE )
+      if ( operatorID == SELSMON && copytimestep == false )
 	{
-	  copy_nts2 = FALSE;
+	  copy_nts2 = false;
 
-	  if ( process_nts1 == TRUE )
+	  if ( process_nts1 )
 	    {
-	      process_nts2 = TRUE;
+	      process_nts2 = true;
 	      its2 = 0;
-	      process_nts1 = FALSE;
+	      process_nts1 = false;
 	    }
 
-	  if ( process_nts2 == TRUE )
+	  if ( process_nts2 )
 	    {
 	      if ( its2++ < nts2 )
-		copy_nts2 = TRUE;
+		copy_nts2 = true;
 	      else
-		process_nts2 = FALSE;
+		process_nts2 = false;
 	    }
 	}
 
@@ -465,7 +459,7 @@ void *Seltime(void *argument)
 		  for ( varID = 0; varID < nvars; varID++ )
 		    {
 		      if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT && tsID2 > 1 ) continue;
-		      nlevel   = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
+		      int nlevel   = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
 		      for ( levelID = 0; levelID < nlevel; levelID++ )
 			{
 			  streamDefRecord(streamID2, varID, levelID);
@@ -480,10 +474,10 @@ void *Seltime(void *argument)
 	    }
 
 	  ncts++;
-	  if ( process_nts2 == FALSE )
+	  if ( !process_nts2 )
 	    {
 	      its2 = 0;
-	      process_nts1 = TRUE;
+	      process_nts1 = true;
 	    }
 
 	  taxisCopyTimestep(taxisID2, taxisID1);
@@ -492,13 +486,13 @@ void *Seltime(void *argument)
 
 	  if ( tsID > 0 && lconstout )
 	    {
-	      lconstout = FALSE;
+	      lconstout = false;
 	      nts = nts1 - 1;
 	      for ( varID = 0; varID < nvars; varID++ )
 		{
 		  if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
 		    {
-		      nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
+		      int nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
 		      for ( levelID = 0; levelID < nlevel; levelID++ )
 			{
 			  streamDefRecord(streamID2, varID, levelID);
@@ -510,7 +504,7 @@ void *Seltime(void *argument)
 		}
 	    }
 
-	  for ( recID = 0; recID < nrecs; recID++ )
+	  for ( int recID = 0; recID < nrecs; recID++ )
 	    {
 	      streamInqRecord(streamID1, &varID, &levelID);
 	      streamDefRecord(streamID2, varID, levelID);
@@ -531,7 +525,7 @@ void *Seltime(void *argument)
 
 	  if ( lnts1 || tsID == 0 )
 	    {
-	      if ( tsID == 0 && nconst && (!lnts1) ) lconstout = TRUE;
+	      if ( tsID == 0 && nconst && (!lnts1) ) lconstout = true;
 
 	      nts = nts1-1;
 	      if ( lnts1 )
@@ -546,9 +540,9 @@ void *Seltime(void *argument)
 			for ( varID = 0; varID < nvars; varID++ )
 			  {
 			    if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
-			    gridID   = vlistInqVarGrid(vlistID1, varID);
-			    gridsize = gridInqSize(gridID);
-			    nlevel   = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
+			    int gridID   = vlistInqVarGrid(vlistID1, varID);
+			    int gridsize = gridInqSize(gridID);
+			    int nlevel   = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
 			    for ( levelID = 0; levelID < nlevel; levelID++ )
 			      {
 				memcpy(vars[it][varID][levelID].ptr,
@@ -565,7 +559,7 @@ void *Seltime(void *argument)
 		  its1++;
 		}
 
-	      for ( recID = 0; recID < nrecs; recID++ )
+	      for ( int recID = 0; recID < nrecs; recID++ )
 		{
 		  streamInqRecord(streamID1, &varID, &levelID);
 		  if ( lnts1 || (vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT) )
@@ -590,15 +584,15 @@ void *Seltime(void *argument)
 
   if ( array ) Free(array);
 
-  for ( isel = 0; isel < nsel; isel++ )
+  for ( int isel = 0; isel < nsel; isel++ )
     {
-      if ( selfound[isel] == FALSE )
+      if ( selfound[isel] == false )
 	{
 	 
 	  int isel2;
 	  int lcont = FALSE;
 	  for ( isel2 = isel+1; isel2 < nsel; isel2++ )
-	    if ( selfound[isel2] == TRUE ) break;
+	    if ( selfound[isel2] ) break;
 	  if ( isel2 == nsel && (nsel-isel) > 1 ) lcont = TRUE;
 
 	  if ( operatorID == SELTIMESTEP )
diff --git a/src/Selvar.c b/src/Selvar.c
index 7cfb7a8..0f35e12 100644
--- a/src/Selvar.c
+++ b/src/Selvar.c
@@ -46,14 +46,9 @@
 
 void *Selvar(void *argument)
 {
-  int nlevs;
-  int code, tabnum, param, gridID, zaxisID, levID;
-  int grididx, zaxisidx;
-  double level;
   int varID2, levelID2;
-  int recID, varID, levelID;
+  int varID, levelID;
   int *intarr = NULL, nsel = 0;
-  int *selfound = NULL;
   double *fltarr = NULL;
   char paramstr[32];
   char varname[CDI_MAX_NAME];
@@ -62,18 +57,15 @@ void *Selvar(void *argument)
   char zaxistypename[CDI_MAX_NAME];
   char zaxisname[CDI_MAX_NAME];
   char **argnames = NULL;
-  int isel;
-  int i;
-  int lcopy = FALSE;
-  int gridsize;
   int nmiss;
   int gridnum = 0;
-  double *array = NULL;
   LIST *ilist = listNew(INT_LIST);
   LIST *flist = listNew(FLT_LIST);
 
   cdoInitialize(argument);
 
+  bool lcopy = UNCHANGED_RECORD;
+
 # define INVERTS_SELECTION(id) (cdoOperatorF2(id) & 1)
 # define TAKES_STRINGS(id) (cdoOperatorF2(id) & 2)
 # define TAKES_INTEGERS(id) (cdoOperatorF2(id) & 4)
@@ -89,17 +81,17 @@ void *Selvar(void *argument)
   int SELZAXIS     = cdoOperatorAdd("selzaxis",     0, 4|2, "list of zaxis types or numbers");
   int SELZAXISNAME = cdoOperatorAdd("selzaxisname", 0, 2,   "list of zaxis names");
   int SELTABNUM    = cdoOperatorAdd("seltabnum",    0, 4,   "table numbers");
-  int DELPARAM     = cdoOperatorAdd("delparam",     0, 2|1, "parameter");
-  int DELCODE      = cdoOperatorAdd("delcode",      0, 1,   "code numbers");
-  int DELNAME      = cdoOperatorAdd("delname",      0, 2|1, "variable names");
+  int DELPARAM     = cdoOperatorAdd("delparam",     1, 2|1, "parameter");
+  int DELCODE      = cdoOperatorAdd("delcode",      1, 1,   "code numbers");
+  int DELNAME      = cdoOperatorAdd("delname",      1, 2|1, "variable names");
   int SELLTYPE     = cdoOperatorAdd("selltype",     0, 4,   "GRIB level types"); 
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
-
   int operatorID = cdoOperatorID();
 
   operatorInputArg(cdoOperatorEnter(operatorID));
 
+  bool ldelete = (cdoOperatorF1(operatorID) == 1) ? true : false;
+
   int args_are_numeric = operatorArgc() > 0 && isdigit(*operatorArgv()[0]);
 
   if ( TAKES_STRINGS(operatorID) && !( TAKES_INTEGERS(operatorID) && args_are_numeric ) )
@@ -108,8 +100,8 @@ void *Selvar(void *argument)
       argnames = operatorArgv();
 
       if ( cdoVerbose )
-	for ( i = 0; i < nsel; i++ )
-	  fprintf(stderr, "name %d = %s\n", i+1, argnames[i]);
+	for ( int i = 0; i < nsel; i++ )
+	  cdoPrint("name %d = %s", i+1, argnames[i]);
     }
   else if ( TAKES_FLOATS(operatorID) )
     {
@@ -117,8 +109,8 @@ void *Selvar(void *argument)
       fltarr = (double *) listArrayPtr(flist);
 
       if ( cdoVerbose )
-	for ( i = 0; i < nsel; i++ )
-	  printf("flt %d = %g\n", i+1, fltarr[i]);
+	for ( int i = 0; i < nsel; i++ )
+	  cdoPrint("flt %d = %g", i+1, fltarr[i]);
     }
   else
     {
@@ -126,14 +118,15 @@ void *Selvar(void *argument)
       intarr = (int *) listArrayPtr(ilist);
 
       if ( cdoVerbose )
-	for ( i = 0; i < nsel; i++ )
-	  printf("int %d = %d\n", i+1, intarr[i]);
+	for ( int i = 0; i < nsel; i++ )
+	  cdoPrint("int %d = %d", i+1, intarr[i]);
     }
 
+  bool *selfound = NULL;
   if ( nsel )
     {
-      selfound = (int*) Malloc(nsel*sizeof(int));
-      for ( i = 0; i < nsel; i++ ) selfound[i] = FALSE;
+      selfound = (bool*) Malloc(nsel*sizeof(bool));
+      for ( int i = 0; i < nsel; i++ ) selfound[i] = false;
     }
 
   /*
@@ -144,7 +137,7 @@ void *Selvar(void *argument)
 
   int vlistID1 = streamInqVlist(streamID1);
   int nvars = vlistNvars(vlistID1);
-  int *vars = (int*) Malloc(nvars*sizeof(int));
+  bool *vars = (bool*) Malloc(nvars*sizeof(bool));
 
   if ( operatorID == SELGRID && !args_are_numeric && nsel == 1 && strncmp(argnames[0], "var=", 4) == 0 )
     {
@@ -157,7 +150,7 @@ void *Selvar(void *argument)
           vlistInqVarName(vlistID1, varID, varname);
           if ( strcmp(varname, gridvarname) == 0 )
             {
-              gridID = vlistInqVarGrid(vlistID1, varID);
+              int gridID = vlistInqVarGrid(vlistID1, varID);
               gridnum = 1 + vlistGridIndex(vlistID1, gridID);
               args_are_numeric = TRUE;
               intarr = &gridnum;
@@ -171,34 +164,33 @@ void *Selvar(void *argument)
   vlistClearFlag(vlistID1);
   for ( varID = 0; varID < nvars; varID++ )
     {
-      vars[varID] = FALSE;
+      vars[varID] = ldelete ? true : false;
 
       vlistInqVarName(vlistID1, varID, varname);
       vlistInqVarStdname(vlistID1, varID, stdname);
-      param    = vlistInqVarParam(vlistID1, varID);
-      code     = vlistInqVarCode(vlistID1, varID);
-      tabnum   = tableInqNum(vlistInqVarTable(vlistID1, varID));
-      gridID   = vlistInqVarGrid(vlistID1, varID);
-      grididx  = vlistGridIndex(vlistID1, gridID);
-      zaxisID  = vlistInqVarZaxis(vlistID1, varID);
-      zaxisidx = vlistZaxisIndex(vlistID1, zaxisID);
-      nlevs    = zaxisInqSize(zaxisID);
+      int param    = vlistInqVarParam(vlistID1, varID);
+      int code     = vlistInqVarCode(vlistID1, varID);
+      int tabnum   = tableInqNum(vlistInqVarTable(vlistID1, varID));
+      int gridID   = vlistInqVarGrid(vlistID1, varID);
+      int grididx  = vlistGridIndex(vlistID1, gridID);
+      int zaxisID  = vlistInqVarZaxis(vlistID1, varID);
+      int zaxisidx = vlistZaxisIndex(vlistID1, zaxisID);
+      int nlevs    = zaxisInqSize(zaxisID);
       gridName(gridInqType(gridID), gridname);
       zaxisInqName(zaxisID, zaxisname);
       zaxisName(zaxisInqType(zaxisID), zaxistypename);
 
       cdiParamToString(param, paramstr, sizeof(paramstr));
 
-      for ( levID = 0; levID < nlevs; levID++ )
+      for ( int levID = 0; levID < nlevs; levID++ )
 	{
-	  level = zaxisInqLevel(zaxisID, levID);
-
-	  if ( operatorID == DELCODE || operatorID == DELNAME || operatorID == DELPARAM )
-	    vlistDefFlag(vlistID1, varID, levID, TRUE);
+	  double level = zaxisInqLevel(zaxisID, levID);
 
-	  for ( isel = 0; isel < nsel; isel++ )
+	  if ( ldelete ) vlistDefFlag(vlistID1, varID, levID, TRUE);
+          
+	  for ( int isel = 0; isel < nsel; isel++ )
 	    {
-              int found = 0;
+              bool found = false;
 	      if ( operatorID == SELCODE )
 		{
 		  found = intarr[isel] == code;
@@ -267,8 +259,8 @@ void *Selvar(void *argument)
 	      if ( found )
 	        {
 		  vlistDefFlag(vlistID1, varID, levID, !INVERTS_SELECTION(operatorID));
-		  selfound[isel] = TRUE;
-                  vars[varID] = TRUE;
+		  selfound[isel] = true;
+                  vars[varID] = ldelete ? false : true;
 	        }
 	    }
 	}
@@ -287,16 +279,16 @@ void *Selvar(void *argument)
               int psvarid = vlist_get_psvarid(vlistID1, zaxisID);
               if ( psvarid != -1 && !vars[psvarid] )
                 {
-                  vars[psvarid] = TRUE;
+                  vars[psvarid] = true;
                   vlistDefFlag(vlistID1, psvarid, 0, !INVERTS_SELECTION(operatorID));
                 }
             }
         }
     }
 
-  for ( isel = 0; isel < nsel; isel++ )
+  for ( int isel = 0; isel < nsel; isel++ )
     {
-      if ( selfound[isel] == FALSE )
+      if ( selfound[isel] == false )
 	{
 	  if ( operatorID == SELCODE || operatorID == DELCODE )
 	    {
@@ -373,9 +365,10 @@ void *Selvar(void *argument)
 
   streamDefVlist(streamID2, vlistID2);
 
+  double *array = NULL;
   if ( ! lcopy )
     {
-      gridsize = vlistGridsizeMax(vlistID1);
+      int gridsize = vlistGridsizeMax(vlistID1);
       if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
       array = (double*) Malloc(gridsize*sizeof(double));
     }
@@ -387,7 +380,7 @@ void *Selvar(void *argument)
 
       streamDefTimestep(streamID2, tsID);
      
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  if ( vlistInqFlag(vlistID1, varID, levelID) == TRUE )
diff --git a/src/Setgrid.c b/src/Setgrid.c
index b02fce6..7dccf52 100644
--- a/src/Setgrid.c
+++ b/src/Setgrid.c
@@ -33,13 +33,8 @@
 
 void *Setgrid(void *argument)
 {
-  int SETGRID, SETGRIDTYPE, SETGRIDAREA, SETGRIDMASK, UNSETGRIDMASK, SETGRIDNUMBER, SETGRIDURI;
-  int operatorID;
-  int streamID1, streamID2 = CDI_UNDEFID;
   int nrecs;
-  int tsID, recID, varID, levelID;
-  int vlistID1, vlistID2;
-  int taxisID1, taxisID2;
+  int recID, varID, levelID;
   int gridID1, gridID2 = -1;
   int ngrids, index;
   int gridtype = -1;
@@ -59,19 +54,18 @@ void *Setgrid(void *argument)
   char *griduri = NULL;
   double *gridmask = NULL;
   double *areaweight = NULL;
-  double *array = NULL;
 
   cdoInitialize(argument);
 
-  SETGRID       = cdoOperatorAdd("setgrid",       0, 0, "grid description file or name");
-  SETGRIDTYPE   = cdoOperatorAdd("setgridtype",   0, 0, "grid type");
-  SETGRIDAREA   = cdoOperatorAdd("setgridarea",   0, 0, "filename with area weights");
-  SETGRIDMASK   = cdoOperatorAdd("setgridmask",   0, 0, "filename with grid mask");
-  UNSETGRIDMASK = cdoOperatorAdd("unsetgridmask", 0, 0, NULL);
-  SETGRIDNUMBER = cdoOperatorAdd("setgridnumber", 0, 0, "grid number and optionally grid position");
-  SETGRIDURI    = cdoOperatorAdd("setgriduri",    0, 0, "reference URI of the horizontal grid");
+  int SETGRID       = cdoOperatorAdd("setgrid",       0, 0, "grid description file or name");
+  int SETGRIDTYPE   = cdoOperatorAdd("setgridtype",   0, 0, "grid type");
+  int SETGRIDAREA   = cdoOperatorAdd("setgridarea",   0, 0, "filename with area weights");
+  int SETGRIDMASK   = cdoOperatorAdd("setgridmask",   0, 0, "filename with grid mask");
+  int UNSETGRIDMASK = cdoOperatorAdd("unsetgridmask", 0, 0, NULL);
+  int SETGRIDNUMBER = cdoOperatorAdd("setgridnumber", 0, 0, "grid number and optionally grid position");
+  int SETGRIDURI    = cdoOperatorAdd("setgriduri",    0, 0, "reference URI of the horizontal grid");
 
-  operatorID = cdoOperatorID();
+  int operatorID = cdoOperatorID();
 
   if ( operatorID != UNSETGRIDMASK )
     operatorInputArg(cdoOperatorEnter(operatorID));  
@@ -100,22 +94,19 @@ void *Setgrid(void *argument)
     }
   else if ( operatorID == SETGRIDAREA )
     {
-      int streamID, vlistID, gridID;
-      char *areafile;
-
       operatorCheckArgc(1);
-      areafile = operatorArgv()[0];
+      char *areafile = operatorArgv()[0];
 
       argument_t *fileargument = file_argument_new(areafile);
-      streamID = streamOpenRead(fileargument);
+      int streamID = streamOpenRead(fileargument);
       file_argument_free(fileargument);
 
-      vlistID = streamInqVlist(streamID);
+      int vlistID = streamInqVlist(streamID);
 
       nrecs = streamInqTimestep(streamID, 0);
       streamInqRecord(streamID, &varID, &levelID);
 
-      gridID = vlistInqVarGrid(vlistID, varID);
+      int gridID = vlistInqVarGrid(vlistID, varID);
       areasize = gridInqSize(gridID);
       areaweight = (double*) Malloc(areasize*sizeof(double));
   
@@ -125,11 +116,9 @@ void *Setgrid(void *argument)
 
       if ( cdoVerbose )
 	{
-	  double arrmean, arrmin, arrmax;
-
-	  arrmean = areaweight[0];
-	  arrmin  = areaweight[0];
-	  arrmax  = areaweight[0];
+	  double arrmean = areaweight[0];
+	  double arrmin  = areaweight[0];
+	  double arrmax  = areaweight[0];
 	  for ( i = 1; i < areasize; i++ )
 	    {
 	      if ( areaweight[i] < arrmin ) arrmin = areaweight[i];
@@ -143,23 +132,19 @@ void *Setgrid(void *argument)
     }
   else if ( operatorID == SETGRIDMASK )
     {
-      int streamID, vlistID, gridID;
-      char *maskfile;
-      double missval;
-
       operatorCheckArgc(1);
-      maskfile = operatorArgv()[0];
+      char *maskfile = operatorArgv()[0];
       argument_t *fileargument = file_argument_new(maskfile);
-      streamID = streamOpenRead(fileargument);
+      int streamID = streamOpenRead(fileargument);
       file_argument_free(fileargument);
 
-      vlistID = streamInqVlist(streamID);
+      int vlistID = streamInqVlist(streamID);
 
       nrecs = streamInqTimestep(streamID, 0);
       streamInqRecord(streamID, &varID, &levelID);
 
-      missval  = vlistInqVarMissval(vlistID, varID);
-      gridID   = vlistInqVarGrid(vlistID, varID);
+      double missval  = vlistInqVarMissval(vlistID, varID);
+      int gridID   = vlistInqVarGrid(vlistID, varID);
       masksize = gridInqSize(gridID);
       gridmask = (double*) Malloc(masksize*sizeof(double));
   
@@ -188,13 +173,13 @@ void *Setgrid(void *argument)
       griduri = operatorArgv()[0];
     }
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
   if ( operatorID == SETGRID )
@@ -306,8 +291,14 @@ void *Setgrid(void *argument)
 	      else cdoAbort("Unsupported grid name: %s", gridname);
 	    }
 
-	  if ( gridID2 == -1 ) cdoAbort("Unsupported grid type!");
-
+	  if ( gridID2 == -1 )
+            {
+              if ( lregular )
+                cdoAbort("No Gaussian reduced grid found!");
+              else
+                cdoAbort("Unsupported grid type!");
+            }
+          
 	  vlistChangeGridIndex(vlistID2, index, gridID2);
 	}
     }
@@ -362,7 +353,7 @@ void *Setgrid(void *argument)
 	}
     }
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
   //vlistPrint(vlistID2);
@@ -373,9 +364,9 @@ void *Setgrid(void *argument)
     gridsize = vlistGridsizeMax(vlistID1);
 
   if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
-  array = (double*) Malloc(gridsize*sizeof(double));
+  double *array = (double*) Malloc(gridsize*sizeof(double));
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Setpartab.c b/src/Setpartab.c
index 6915c5f..e415090 100644
--- a/src/Setpartab.c
+++ b/src/Setpartab.c
@@ -73,7 +73,7 @@ static pthread_mutex_t udunitsMutex;
 #endif
 
 
-ut_system *ut_read = NULL;
+static ut_system *ut_read = NULL;
 
 static
 void udunitsInitialize(void)
@@ -174,26 +174,26 @@ void *get_converter(char *src_unit_str, char *tgt_unit_str, int *rstatus)
 
 typedef struct
 {
-  int convert;
-  int remove;
+  bool convert;
+  bool remove;
   // missing value
-  int changemissval;
+  bool changemissval;
   double missval_old;
   //
-  int lfactor;
+  bool lfactor;
   double factor;
   //
-  int checkvalid;
+  bool checkvalid;
   double valid_min;
   double valid_max;
   //
-  int check_min_mean_abs;
+  bool check_min_mean_abs;
   double ok_min_mean_abs;
   //
-  int check_max_mean_abs;
+  bool check_max_mean_abs;
   double ok_max_mean_abs;
   // units
-  int changeunits;
+  bool changeunits;
   char units_old[CDI_MAX_NAME];
   char units[CDI_MAX_NAME];
   // varname
@@ -213,9 +213,9 @@ void defineVarAttText(int vlistID2, int varID, const char *attname, const char *
 static
 void convertVarUnits(var_t *vars, int varID, char *name)
 {
-  if ( vars[varID].convert == FALSE ) vars[varID].changeunits = FALSE;
+  if ( vars[varID].convert == false ) vars[varID].changeunits = false;
 
-  if ( vars[varID].changeunits == TRUE )
+  if ( vars[varID].changeunits )
     {
       char *units = vars[varID].units;
       char *units_old = vars[varID].units_old;
@@ -238,7 +238,7 @@ void convertVarUnits(var_t *vars, int varID, char *name)
 	    }
 	  else
 	    cdoWarning("%s - converting units from [%s] to [%s] failed!", name, units_old, units);
-	  vars[varID].changeunits = FALSE;
+	  vars[varID].changeunits = false;
 	}
       else
 	{
@@ -250,12 +250,12 @@ void convertVarUnits(var_t *vars, int varID, char *name)
 	    }
 	}
 #else
-      static int lwarn_udunits = TRUE;
+      static bool lwarn_udunits = true;
       if ( lwarn_udunits )
 	{
 	  cdoWarning("%s - converting units from [%s] to [%s] failed, UDUNITS2 support not compiled in!", name,units_old, units);
-	  vars[varID].changeunits = FALSE;
-	  lwarn_udunits = FALSE;
+	  vars[varID].changeunits = false;
+	  lwarn_udunits = false;
 	}
 #endif
     }
@@ -274,7 +274,7 @@ void defineVarUnits(var_t *vars, int vlistID2, int varID, char *units)
     {
       if ( len1 > 0 && len2 > 0 )
 	{
-	  vars[varID].changeunits = TRUE;
+	  vars[varID].changeunits = true;
 	  strcpy(vars[varID].units_old, units_old);
 	  strcpy(vars[varID].units, units);
 	}
@@ -293,7 +293,7 @@ void read_partab(pt_mode_t ptmode, int nvars, int vlistID2, var_t *vars)
   int nml_longname, nml_units, nml_comment, nml_ltype, nml_delete, nml_convert, nml_missval, nml_factor;
   int nml_cell_methods, nml_cell_measures;
   int nml_valid_min, nml_valid_max, nml_ok_min_mean_abs, nml_ok_max_mean_abs;
-  int locc, i;
+  int i;
   int code, out_code, table, ltype, remove, convert;
   int nml_index = 0;
   int codenum, tabnum, levtype, param;
@@ -359,10 +359,10 @@ void read_partab(pt_mode_t ptmode, int nvars, int vlistID2, var_t *vars)
 
 	  if ( cdoVerbose ) namelistPrint(nml);
 
-	  locc = FALSE;
+	  bool locc = false;
 	  for ( i = 0; i < nml->size; i++ )
 	    {
-	      if ( nml->entry[i]->occ ) { locc = TRUE; break; }
+	      if ( nml->entry[i]->occ ) { locc = true; break; }
 	    }
 
 	  if ( locc )
@@ -446,8 +446,8 @@ void read_partab(pt_mode_t ptmode, int nvars, int vlistID2, var_t *vars)
 		  if ( nml->entry[nml_comment]->occ  )  defineVarAttText(vlistID2, varID, "comment", comment);
 		  if ( nml->entry[nml_cell_methods]->occ  ) defineVarAttText(vlistID2, varID, "cell_methods", cell_methods);
 		  if ( nml->entry[nml_cell_measures]->occ ) defineVarAttText(vlistID2, varID, "cell_measures", cell_measures);
-		  if ( nml->entry[nml_delete]->occ && remove == 1 ) vars[varID].remove = TRUE;
-		  if ( nml->entry[nml_convert]->occ )   vars[varID].convert = convert==0 ? FALSE : TRUE;
+		  if ( nml->entry[nml_delete]->occ && remove == 1 ) vars[varID].remove = true;
+		  if ( nml->entry[nml_convert]->occ )   vars[varID].convert = convert==0 ? false : true;
 		  if ( nml->entry[nml_param]->occ )     vlistDefVarParam(vlistID2, varID, stringToParam(paramstr));
 		  if ( nml->entry[nml_out_param]->occ ) vlistDefVarParam(vlistID2, varID, stringToParam(out_paramstr));
 		  if ( nml->entry[nml_datatype]->occ )
@@ -468,32 +468,32 @@ void read_partab(pt_mode_t ptmode, int nvars, int vlistID2, var_t *vars)
 			{
 			  if ( cdoVerbose ) 
 			    cdoPrint("%s - change missval from %g to %g", name, missval_old, missval);
-			  vars[varID].changemissval = TRUE;
+			  vars[varID].changemissval = true;
 			  vars[varID].missval_old = missval_old;
 			  vlistDefVarMissval(vlistID2, varID, missval);
 			}
 		    }
 		  if ( nml->entry[nml_factor]->occ )
 		    {
-		      vars[varID].lfactor = TRUE;
+		      vars[varID].lfactor = true;
 		      vars[varID].factor = factor;
 		      if ( cdoVerbose ) 
 			cdoPrint("%s - scale factor %g", name, factor);
 		    }
 		  if ( nml->entry[nml_valid_min]->occ && nml->entry[nml_valid_max]->occ )
 		    {
-		      vars[varID].checkvalid = TRUE;
+		      vars[varID].checkvalid = true;
 		      vars[varID].valid_min = valid_min;
 		      vars[varID].valid_max = valid_max;
 		    }
 		  if ( nml->entry[nml_ok_min_mean_abs]->occ )
 		    {
-		      vars[varID].check_min_mean_abs = TRUE;
+		      vars[varID].check_min_mean_abs = true;
 		      vars[varID].ok_min_mean_abs = ok_min_mean_abs;
 		    }
 		  if ( nml->entry[nml_ok_max_mean_abs]->occ )
 		    {
-		      vars[varID].check_max_mean_abs = TRUE;
+		      vars[varID].check_max_mean_abs = true;
 		      vars[varID].ok_max_mean_abs = ok_max_mean_abs;
 		    }
 		}
@@ -600,17 +600,17 @@ void *Setpartab(void *argument)
   int nrecs;
   int varID, levelID;
   int nmiss;
-  int delvars = FALSE;
+  bool delvars = false;
   int tableID = -1;
   int tableformat = 0;
   double missval;
 
   cdoInitialize(argument);
 
-  int SETPARTAB  = cdoOperatorAdd("setpartab",  0, 0, "parameter table name");
-  int SETPARTABC = cdoOperatorAdd("setpartabc", 0, 0, "parameter table name");
-  int SETPARTABP = cdoOperatorAdd("setpartabp", 0, 0, "parameter table name");
-  int SETPARTABN = cdoOperatorAdd("setpartabn", 0, 0, "parameter table name");
+  int SETCODETAB = cdoOperatorAdd("setcodetab",  0, 0, "parameter code table name");
+  int SETPARTABC = cdoOperatorAdd("setpartabc",  0, 0, "parameter table name");
+  int SETPARTABP = cdoOperatorAdd("setpartabp",  0, 0, "parameter table name");
+  int SETPARTABN = cdoOperatorAdd("setpartabn",  0, 0, "parameter table name");
 
   int operatorID = cdoOperatorID();
 
@@ -618,17 +618,17 @@ void *Setpartab(void *argument)
 
   if ( operatorArgc() < 1 ) cdoAbort("Too few arguments!");
 
-  int convert_data = FALSE;
+  bool convert_data = false;
   if ( operatorArgc() == 2 )
     {
-      if ( strcmp("convert", operatorArgv()[1]) == 0 ) convert_data = TRUE;
+      if ( strcmp("convert", operatorArgv()[1]) == 0 ) convert_data = true;
       else cdoAbort("Unknown parameter: >%s<", operatorArgv()[1]); 
     }
 
   if ( operatorArgc() > 2 ) cdoAbort("Too many arguments!");
 
   pt_mode_t ptmode = CODE_NUMBER;
-  if      ( operatorID == SETPARTAB  ) ptmode = CODE_NUMBER;
+  if      ( operatorID == SETCODETAB ) ptmode = CODE_NUMBER;
   else if ( operatorID == SETPARTABC ) ptmode = CODE_NUMBER;
   else if ( operatorID == SETPARTABP ) ptmode = PARAMETER_ID;
   else if ( operatorID == SETPARTABN ) ptmode = VARIABLE_NAME;
@@ -676,7 +676,7 @@ void *Setpartab(void *argument)
   memset(vars, 0, nvars*sizeof(var_t));
 
   if ( convert_data )
-    for ( varID = 0; varID < nvars; ++varID ) vars[varID].convert = TRUE;
+    for ( varID = 0; varID < nvars; ++varID ) vars[varID].convert = true;
 
   if ( tableformat == 0 )
     {
@@ -714,7 +714,7 @@ void *Setpartab(void *argument)
       for ( int varID = 0; varID < nvars; ++varID )
 	if ( vars[varID].remove )
           {
-            delvars = TRUE;
+            delvars = true;
             break;
           }
 
@@ -797,7 +797,7 @@ void *Setpartab(void *argument)
 	  gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID2));
 	  if ( vlistInqVarNumber(vlistID2, varID2) != CDI_REAL ) gridsize *= 2;
 
-	  if ( nmiss > 0 && vars[varID].changemissval == TRUE )
+	  if ( nmiss > 0 && vars[varID].changemissval )
 	    {
 	      for ( long i = 0; i < gridsize; ++i )
 		{
@@ -805,7 +805,7 @@ void *Setpartab(void *argument)
 		}
 	    }
 
-	  if ( vars[varID].lfactor == TRUE )
+	  if ( vars[varID].lfactor )
 	    {
 	      for ( long i = 0; i < gridsize; ++i )
 		{
@@ -814,7 +814,7 @@ void *Setpartab(void *argument)
 	    }
 
 #if defined(HAVE_UDUNITS2)
-	  if ( vars[varID].changeunits == TRUE )
+	  if ( vars[varID].changeunits )
 	    {
 	      int nerr = 0;
 	      for ( long i = 0; i < gridsize; ++i )
@@ -829,7 +829,7 @@ void *Setpartab(void *argument)
 		{
 		  cdoWarning("Udunits: Error converting units from [%s] to [%s], parameter: %s",
 			     vars[varID].units_old, vars[varID].units, vars[varID].name);
-		  vars[varID].changeunits = FALSE;
+		  vars[varID].changeunits = false;
 		}
 	    }
 #endif
diff --git a/src/Setrcaname.c b/src/Setrcaname.c
index 79b7b75..c90b5e9 100644
--- a/src/Setrcaname.c
+++ b/src/Setrcaname.c
@@ -24,38 +24,32 @@
 
 void *Setrcaname(void *argument)
 {
-  int streamID1, streamID2 = CDI_UNDEFID;
   int nrecs;
-  int tsID, recID, varID, levelID;
-  int vlistID1, vlistID2;
-  int taxisID1, taxisID2;
+  int recID, varID, levelID;
   char **rcsnames;
-  FILE *fp;
   char line[MAX_LINE_LEN];
   char sname[CDI_MAX_NAME], sdescription[CDI_MAX_NAME], sunits[CDI_MAX_NAME];
   int scode, sltype, slevel;
-  int nvars;
   int zaxisID, ltype, code, nlev;
   int level;
-  int lcopy = FALSE;
   int gridsize, nmiss;
   double *array = NULL;
 
   cdoInitialize(argument);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
   operatorInputArg("file name with RCA names");
   rcsnames = operatorArgv();
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  nvars = vlistNvars(vlistID2);
+  int nvars = vlistNvars(vlistID2);
 
-  fp = fopen(rcsnames[0], "r");
+  FILE *fp = fopen(rcsnames[0], "r");
   if ( fp != NULL )
     {
       while ( readline(fp, line, MAX_LINE_LEN) )
@@ -110,11 +104,11 @@ void *Setrcaname(void *argument)
       perror(rcsnames[0]);
     }
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
@@ -124,7 +118,7 @@ void *Setrcaname(void *argument)
       array = (double*) Malloc(gridsize*sizeof(double));
     }
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Settime.c b/src/Settime.c
index 81a873b..5ee5cb5 100644
--- a/src/Settime.c
+++ b/src/Settime.c
@@ -54,7 +54,7 @@ int get_tunits(const char *unit, int *incperiod, int *incunit, int *tunit)
   else if ( memcmp(unit, "days", len)    == 0 ) { *incunit = 86400; *tunit = TUNIT_DAY;     }
   else if ( memcmp(unit, "months", len)  == 0 ) { *incunit =     1; *tunit = TUNIT_MONTH;   }
   else if ( memcmp(unit, "years", len)   == 0 ) { *incunit =    12; *tunit = TUNIT_YEAR;    }
-  else cdoAbort("time unit >%s< unsupported", unit);
+  else cdoAbort("Time unit >%s< unsupported!", unit);
 
   if ( *tunit == TUNIT_HOUR )
     {
@@ -102,6 +102,41 @@ void shifttime(int calendar, int tunit, int ijulinc, int *pdate, int *ptime)
     }
 }
 
+static
+void gen_bounds(int calendar, int tunit, int vdate, int vtime, int *vdateb, int *vtimeb)
+{
+  juldate_t juldate;
+  int year, month, day;
+  //int hour, minute, second;
+  UNUSED(vtime);
+  
+  vdateb[0] = vdate;
+  vdateb[1] = vdate;
+  vtimeb[0] = 0;
+  vtimeb[1] = 0;
+          
+  cdiDecodeDate(vdate, &year, &month, &day);
+  if ( tunit == TUNIT_MONTH )
+    {
+      vdateb[0] = cdiEncodeDate(year, month, 1);
+      month++;
+      if ( month > 12 ) { month = 1; year++; }
+      vdateb[1] = cdiEncodeDate(year, month, 1);
+    }
+  else if ( tunit == TUNIT_YEAR )
+    {
+      vdateb[0] = cdiEncodeDate(year,   1, 1);
+      vdateb[1] = cdiEncodeDate(year+1, 1, 1);
+    }
+  else if ( tunit == TUNIT_DAY )
+    {
+      vdateb[0] = vdate;
+      juldate = juldate_encode(calendar, vdateb[0], vtimeb[0]);
+      juldate = juldate_add_seconds(86400, juldate);
+      juldate_decode(calendar, juldate, &vdateb[1], &vtimeb[1]);
+    }
+}
+
 
 void *Settime(void *argument)
 {
@@ -117,7 +152,7 @@ void *Settime(void *argument)
   int ijulinc = 0, incperiod = 1, incunit = 86400;
   int year = 1, month = 1, day = 1, hour = 0, minute = 0, second = 0;
   int day0;
-  int taxis_has_bounds, copy_timestep = FALSE;
+  int copy_timestep = FALSE;
   int newcalendar = CALENDAR_STANDARD;
   // int nargs;
   const char *datestr, *timestr;
@@ -133,6 +168,7 @@ void *Settime(void *argument)
   int SETTIME     = cdoOperatorAdd("settime",      0,  1, "time (format: hh:mm:ss)");
   int SETTUNITS   = cdoOperatorAdd("settunits",    0,  1, "time units (seconds, minutes, hours, days, months, years)");
   int SETTAXIS    = cdoOperatorAdd("settaxis",     0, -2, "date,time<,increment> (format YYYY-MM-DD,hh:mm:ss)");
+  int SETTBOUNDS  = cdoOperatorAdd("settbounds",   0,  1, "frequency (day, month, year)");
   int SETREFTIME  = cdoOperatorAdd("setreftime",   0, -2, "date,time<,units> (format YYYY-MM-DD,hh:mm:ss)");
   int SETCALENDAR = cdoOperatorAdd("setcalendar",  0,  1, "calendar (standard, proleptic_gregorian, 360_day, 365_day, 366_day)");
   int SHIFTTIME   = cdoOperatorAdd("shifttime",    0,  1, "shift value");
@@ -229,13 +265,17 @@ void *Settime(void *argument)
       /* increment in seconds */
       ijulinc = incperiod * incunit;
     }
-  else if ( operatorID == SETTUNITS )
+  else if ( operatorID == SETTUNITS || operatorID == SETTBOUNDS )
     {
       operatorCheckArgc(1);
       int idum;
       const char *timeunits = operatorArgv()[0];
       incperiod = 0;
       get_tunits(timeunits, &incperiod, &idum, &tunit);
+
+      if ( operatorID == SETTBOUNDS &&
+           !(tunit == TUNIT_DAY || tunit == TUNIT_MONTH || tunit == TUNIT_YEAR) )
+        cdoAbort("Unsupported frequency %s! Use day, month or year.", timeunits);
     }
   else if ( operatorID == SETCALENDAR )
     {
@@ -268,7 +308,7 @@ void *Settime(void *argument)
   int vlistID2 = vlistDuplicate(vlistID1);
 
   int taxisID1 = vlistInqTaxis(vlistID1);
-  taxis_has_bounds = taxisHasBounds(taxisID1);
+  int taxis_has_bounds = taxisHasBounds(taxisID1);
   int ntsteps  = vlistNtsteps(vlistID1);
   int nvars    = vlistNvars(vlistID1);
 
@@ -412,6 +452,19 @@ void *Settime(void *argument)
 	      juldate = juldate_add_seconds(ijulinc, juldate);
 	    }
 	}
+      else if ( operatorID == SETTBOUNDS )
+	{
+          gen_bounds(calendar, tunit, vdate, vtime, vdateb, vtimeb);
+          
+          if ( CDO_CMOR_Mode )
+            {
+              juldate_t juldate1 = juldate_encode(calendar, vdateb[0], vtimeb[0]);
+              juldate_t juldate2 = juldate_encode(calendar, vdateb[1], vtimeb[1]);
+              double seconds = juldate_to_seconds(juldate_sub(juldate2, juldate1)) / 2;
+              juldate_t juldatem = juldate_add_seconds((int)lround(seconds), juldate1);
+              juldate_decode(calendar, juldatem, &vdate, &vtime);
+            }
+	}
       else if ( operatorID == SHIFTTIME )
 	{
 	  shifttime(calendar, tunit, ijulinc, &vdate, &vtime);
@@ -459,7 +512,7 @@ void *Settime(void *argument)
 
 	  taxisDefVdate(taxisID2, vdate);
 	  taxisDefVtime(taxisID2, vtime);
-	  if ( taxis_has_bounds )
+	  if ( taxis_has_bounds || operatorID == SETTBOUNDS )
 	    {
 	      taxisDefVdateBounds(taxisID2, vdateb[0], vdateb[1]);
 	      taxisDefVtimeBounds(taxisID2, vtimeb[0], vtimeb[1]);
diff --git a/src/Sinfo.c b/src/Sinfo.c
index 9762015..e75b9d8 100644
--- a/src/Sinfo.c
+++ b/src/Sinfo.c
@@ -129,7 +129,7 @@ void *Sinfo(void *argument)
       set_text_color(stdout, BRIGHT, BLACK);
       if ( lensemble )
 	fprintf(stdout, "%6d : Institut Source   Steptype Einfo Levels Num    Points Num Dtype : ",  -(indf+1));
-      else if ( nsubtypes > 0 )
+      else if ( nsubtypes > 1 )
 	fprintf(stdout, "%6d : Institut Source   Steptype Subtypes Levels Num    Points Num Dtype : ",  -(indf+1));
       else
 	fprintf(stdout, "%6d : Institut Source   Steptype Levels Num    Points Num Dtype : ",  -(indf+1));
@@ -196,7 +196,7 @@ void *Sinfo(void *argument)
 		fprintf(stdout, "--/-- ");
 	    }
 
-          if ( nsubtypes > 0 )
+          if ( nsubtypes > 1 )
             {
               int subtypeID = vlistInqVarSubtype(vlistID, varID);
               int subtypesize = subtypeInqSize(subtypeID);
@@ -269,7 +269,7 @@ void *Sinfo(void *argument)
 
       printZaxisInfo(vlistID);
 
-      if ( nsubtypes > 0 )
+      if ( nsubtypes > 1 )
         {
           fprintf(stdout, "   Subtypes");
           fprintf(stdout, " :\n");
diff --git a/src/Smooth.c b/src/Smooth.c
new file mode 100644
index 0000000..36e1170
--- /dev/null
+++ b/src/Smooth.c
@@ -0,0 +1,516 @@
+/*
+  This file is part of CDO. CDO is a collection of Operators to
+  manipulate and analyse Climate model Data.
+
+  Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.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.
+*/
+
+/*
+   This module contains the following operators:
+
+      Smoothstat       smooth9             running 9-point-average
+*/
+#include <time.h> // clock()
+
+#include <cdi.h>
+#include "cdo.h"
+#include "cdo_int.h"
+#include "pstream.h"
+#include "grid.h"
+#include "constants.h" // planet radius
+#include "pmlist.h"
+
+#include "grid_search.h"
+
+enum {FORM_LINEAR};
+static const char *Form[] = {"linear"};
+
+typedef struct {
+  int maxpoints;
+  int form;
+  double radius;
+  double weight0;
+  double weightR;
+} smoothpoint_t;
+
+
+double intlin(double x, double y1, double x1, double y2, double x2);
+
+double smooth_knn_compute_weights(unsigned num_neighbors, const int *restrict src_grid_mask, struct gsknn *knn, double search_radius, double weight0, double weightR)
+{
+  int *restrict nbr_mask = knn->mask;
+  const int *restrict nbr_add = knn->add;
+  double *restrict nbr_dist = knn->dist;
+
+  // Compute weights based on inverse distance if mask is false, eliminate those points
+  double dist_tot = 0.; // sum of neighbor distances (for normalizing)
+
+  for ( unsigned n = 0; n < num_neighbors; ++n )
+    {
+      nbr_mask[n] = FALSE;
+      if ( nbr_add[n] >= 0 && src_grid_mask[nbr_add[n]] )
+        {
+          nbr_dist[n] = intlin(nbr_dist[n], weight0, 0, weightR, search_radius);
+          dist_tot += nbr_dist[n];
+          nbr_mask[n] = TRUE;
+        }
+    }
+
+  return dist_tot;
+}
+
+
+unsigned smooth_knn_normalize_weights(unsigned num_neighbors, double dist_tot, struct gsknn *knn)
+{
+  const int *restrict nbr_mask = knn->mask;
+  int *restrict nbr_add = knn->add;
+  double *restrict nbr_dist = knn->dist;
+
+  // Normalize weights and store the link
+  unsigned nadds = 0;
+
+  for ( unsigned n = 0; n < num_neighbors; ++n )
+    {
+      if ( nbr_mask[n] )
+        {
+          nbr_dist[nadds] = nbr_dist[n]/dist_tot;
+          nbr_add[nadds]  = nbr_add[n];
+          nadds++;
+        }
+    }
+
+  return nadds;
+}
+
+static
+void smooth(int gridID, double missval, const double *restrict array1, double *restrict array2, int *nmiss, smoothpoint_t spoint)
+{
+  *nmiss = 0;
+  int gridID0 = gridID;
+  unsigned gridsize = gridInqSize(gridID);
+  unsigned num_neighbors = spoint.maxpoints;
+  if ( num_neighbors > gridsize ) num_neighbors = gridsize;
+
+  int *mask = (int*) Malloc(gridsize*sizeof(int));
+  for ( unsigned i = 0; i < gridsize; ++i )
+    mask[i] = DBL_IS_EQUAL(array1[i], missval) ? 0 : 1;
+  
+  double *xvals = (double*) Malloc(gridsize*sizeof(double));
+  double *yvals = (double*) Malloc(gridsize*sizeof(double));
+
+  if ( gridInqType(gridID) == GRID_GME ) gridID = gridToUnstructured(gridID, 0);
+
+  if ( gridInqType(gridID) != GRID_UNSTRUCTURED && gridInqType(gridID) != GRID_CURVILINEAR )
+    gridID = gridToCurvilinear(gridID, 0);
+
+  gridInqXvals(gridID, xvals);
+  gridInqYvals(gridID, yvals);
+
+  /* Convert lat/lon units if required */
+  char units[CDI_MAX_NAME];
+  gridInqXunits(gridID, units);
+  grid_to_radian(units, gridsize, xvals, "grid center lon");
+  gridInqYunits(gridID, units);
+  grid_to_radian(units, gridsize, yvals, "grid center lat");
+  
+  struct gsknn **knn = (struct gsknn**) Malloc(ompNumThreads*sizeof(struct gsknn*));
+  for ( int i = 0; i < ompNumThreads; i++ )
+    knn[i] = gridsearch_knn_new(num_neighbors);
+
+  clock_t start, finish;
+
+  start = clock();
+
+  struct gridsearch *gs = NULL;
+
+  if ( num_neighbors == 1 )
+    gs = gridsearch_create_nn(gridsize, xvals, yvals);
+  else
+    gs = gridsearch_create(gridsize, xvals, yvals);
+
+  gs->search_radius = spoint.radius;
+
+  finish = clock();
+
+  if ( cdoVerbose ) printf("gridsearch created: %.2f seconds\n", ((double)(finish-start))/CLOCKS_PER_SEC);
+
+  if ( cdoVerbose ) progressInit();
+
+  start = clock();
+
+  double findex = 0;
+
+#if defined(_OPENMP)
+#pragma omp parallel for schedule(dynamic) default(none) shared(cdoVerbose, knn, spoint, findex, mask, array1, array2, xvals, yvals, gs, gridsize, nmiss, missval)
+#endif
+  for ( unsigned i = 0; i < gridsize; ++i )
+    {
+      int ompthID = cdo_omp_get_thread_num();
+      
+#if defined(_OPENMP)
+#include "pragma_omp_atomic_update.h"
+#endif
+      findex++;
+      if ( cdoVerbose && cdo_omp_get_thread_num() == 0 ) progressStatus(0, 1, findex/gridsize);
+     
+      unsigned nadds = gridsearch_knn(gs, knn[ompthID], xvals[i], yvals[i]);
+
+      // Compute weights based on inverse distance if mask is false, eliminate those points
+      double dist_tot = smooth_knn_compute_weights(nadds, mask, knn[ompthID], spoint.radius, spoint.weight0, spoint.weightR);
+
+      // Normalize weights and store the link
+      nadds = smooth_knn_normalize_weights(nadds, dist_tot, knn[ompthID]);
+      if ( nadds )
+        {
+          const int *restrict nbr_add = knn[ompthID]->add;
+          const double *restrict nbr_dist = knn[ompthID]->dist;
+          /*
+          printf("n %u %d nadds %u dis %g\n", i, nbr_add[0], nadds, nbr_dist[0]);
+          for ( unsigned n = 0; n < nadds; ++n )
+            printf("   n %u add %d dis %g\n", n, nbr_add[n], nbr_dist[n]);
+          */
+          double result = 0;
+          for ( unsigned n = 0; n < nadds; ++n ) result += array1[nbr_add[n]]*nbr_dist[n];
+          array2[i] = result;
+        }
+      else
+        {
+#if defined(_OPENMP)
+#include "pragma_omp_atomic_update.h"
+#endif
+          (*nmiss)++;
+          array2[i] = missval;
+        }
+    }
+
+  finish = clock();
+
+  if ( cdoVerbose ) printf("gridsearch nearest: %.2f seconds\n", ((double)(finish-start))/CLOCKS_PER_SEC);
+
+  if ( gs ) gridsearch_delete(gs);
+
+  for ( int i = 0; i < ompNumThreads; i++ )
+    gridsearch_knn_delete(knn[i]);
+
+  if ( gridID0 != gridID ) gridDestroy(gridID);
+
+  Free(mask);
+  Free(xvals);
+  Free(yvals);
+}
+
+static inline
+void smooth9_sum(size_t ij, short *mask, double sfac, const double *restrict array, double *avg, double *divavg)
+{
+  if ( mask[ij] ) { *avg += sfac*array[ij]; *divavg += sfac; }
+}
+
+static
+void smooth9(int gridID, double missval, const double *restrict array1, double *restrict array2, int *nmiss)
+{
+  size_t gridsize = gridInqSize(gridID);
+  size_t nlon = gridInqXsize(gridID);	 
+  size_t nlat = gridInqYsize(gridID);
+  int grid_is_cyclic = gridIsCircular(gridID);
+
+  short *mask = (short*) Malloc(gridsize*sizeof(short));
+
+  for ( size_t i = 0; i < gridsize; ++i ) 
+    {		
+      if ( DBL_IS_EQUAL(missval, array1[i]) ) mask[i] = 0;
+      else mask[i] = 1;
+    }
+ 
+  *nmiss = 0;
+  for ( size_t i = 0; i < nlat; i++ )
+    {
+      for ( size_t j = 0; j < nlon; j++ )
+        {		      
+          double avg = 0;
+          double divavg = 0; 	  		     			
+
+          if ( (i == 0) || (j == 0) || (i == (nlat-1)) || (j == (nlon-1)) )
+            {
+              size_t ij = j+nlon*i;
+              if ( mask[ij] )
+                {
+                  avg += array1[ij];  divavg+= 1;					     		       
+                  /* upper left corner */
+                  if ( (i != 0) && (j != 0) ) 
+                    smooth9_sum(((i-1)*nlon)+j-1, mask, 0.3, array1, &avg, &divavg);
+                  else if ( i != 0 && grid_is_cyclic ) 
+                    smooth9_sum((i-1)*nlon+j-1+nlon, mask, 0.3, array1, &avg, &divavg);
+			      
+                  /* upper cell */
+                  if ( i != 0 ) 
+                    smooth9_sum(((i-1)*nlon)+j, mask, 0.5, array1, &avg, &divavg);
+                  
+                  /* upper right corner */
+                  if ( (i != 0) && (j != (nlon-1)) ) 
+                    smooth9_sum(((i-1)*nlon)+j+1, mask, 0.3, array1, &avg, &divavg);
+                  else if ( (i !=0 ) && grid_is_cyclic )
+                    smooth9_sum((i-1)*nlon+j+1-nlon, mask, 0.3, array1, &avg, &divavg);
+                  
+                  /* left cell */
+                  if  ( j != 0 ) 
+                    smooth9_sum(((i)*nlon)+j-1, mask, 0.5, array1, &avg, &divavg);
+                  else if ( grid_is_cyclic )
+                    smooth9_sum(i*nlon-1+nlon, mask, 0.5, array1, &avg, &divavg);
+                  
+                  /* right cell */
+                  if ( j!=(nlon-1) ) 
+                    smooth9_sum((i*nlon)+j+1, mask, 0.5, array1, &avg, &divavg);
+                  else if ( grid_is_cyclic )
+                    smooth9_sum(i*nlon+j+1-nlon, mask, 0.5, array1, &avg, &divavg);
+                  
+                  /* lower left corner */
+                  if ( mask[ij] &&  ( (i!=(nlat-1))&& (j!=0) ) )
+                    smooth9_sum(((i+1)*nlon+j-1), mask, 0.3, array1, &avg, &divavg);
+                  else if ( (i != (nlat-1)) && grid_is_cyclic ) 
+                    smooth9_sum((i+1)*nlon-1+nlon, mask, 0.3, array1, &avg, &divavg);
+                  
+                  /* lower cell */
+                  if  ( i != (nlat-1) ) 
+                    smooth9_sum(((i+1)*nlon)+j, mask, 0.5, array1, &avg, &divavg);
+                  
+                  /* lower right corner */
+                  if ( (i != (nlat-1)) && (j != (nlon-1)) )
+                    smooth9_sum(((i+1)*nlon)+j+1, mask, 0.3, array1, &avg, &divavg);
+                  else if ( (i != (nlat-1)) && grid_is_cyclic )
+                    smooth9_sum(((i+1)*nlon)+j+1-nlon, mask, 0.3, array1, &avg, &divavg);
+                }
+            }
+          else if ( mask[j+nlon*i] )
+            {			 
+              avg += array1[j+nlon*i]; divavg+= 1;
+			    
+              smooth9_sum(((i-1)*nlon)+j-1, mask, 0.3, array1, &avg, &divavg);
+              smooth9_sum(((i-1)*nlon)+j,   mask, 0.5, array1, &avg, &divavg);
+              smooth9_sum(((i-1)*nlon)+j+1, mask, 0.3, array1, &avg, &divavg);
+              smooth9_sum(((i)*nlon)+j-1,   mask, 0.5, array1, &avg, &divavg);
+              smooth9_sum((i*nlon)+j+1,     mask, 0.5, array1, &avg, &divavg);
+              smooth9_sum(((i+1)*nlon+j-1), mask, 0.3, array1, &avg, &divavg);
+              smooth9_sum(((i+1)*nlon)+j,   mask, 0.5, array1, &avg, &divavg);
+              smooth9_sum(((i+1)*nlon)+j+1, mask, 0.3, array1, &avg, &divavg);
+            }
+
+          if ( fabs(divavg) > 0 )
+            {
+              array2[i*nlon+j] = avg/divavg;			
+            }
+          else 
+            {
+              array2[i*nlon+j] = missval;					
+              (*nmiss)++;
+            }
+        }			    	     
+    }
+
+  Free(mask);
+}
+
+static
+double convert_radius(const char *string)
+{
+  char *endptr = NULL;
+  double radius = strtod(string, &endptr);
+
+  if ( *endptr != 0 )
+    {
+      if ( strcmp(endptr, "km") == 0 )
+        radius = 360*((radius*1000)/(2*PlanetRadius*M_PI));
+      else if ( strncmp(endptr, "m", 1) == 0 )
+        radius = 360*((radius)/(2*PlanetRadius*M_PI));
+      else if ( strncmp(endptr, "deg", 3) == 0 )
+        ;
+      else if ( strncmp(endptr, "rad", 3) == 0 )
+        radius *= RAD2DEG;
+      else
+        cdoAbort("Float parameter >%s< contains invalid character at position %d!",
+                 string, (int)(endptr-string+1));
+    }
+
+  if ( radius > 180. ) radius = 180.;
+
+  return radius;
+}
+
+static
+int convert_form(const char *formstr)
+{
+  int form = FORM_LINEAR;
+
+  if ( strcmp(formstr, "linear") == 0 ) form = FORM_LINEAR;
+  else cdoAbort("form=%s unsupported!", formstr);
+
+  return form;
+}
+
+
+void *Smooth(void *argument)
+{
+  int nrecs;
+  int varID, levelID;
+  int nmiss;
+  int xnsmooth = 1;
+  smoothpoint_t spoint;
+  spoint.maxpoints = INT_MAX;
+  spoint.radius    = 1;
+  spoint.form      = FORM_LINEAR;
+  spoint.weight0   = 0.25;
+  spoint.weightR   = 0.25;
+
+  cdoInitialize(argument);
+
+  int SMOOTH  = cdoOperatorAdd("smooth",   0,   0, NULL);
+  int SMOOTH9 = cdoOperatorAdd("smooth9",  0,   0, NULL);
+ 
+  int operatorID = cdoOperatorID();
+
+  if ( operatorID == SMOOTH )
+    {
+      int pargc = operatorArgc();
+
+      if ( pargc )
+        {
+          char **pargv = operatorArgv();
+          pml_t *pml = pml_create("SMOOTH");
+
+          PML_ADD_INT(pml, nsmooth,   1, "Number of times to smooth");
+          PML_ADD_INT(pml, maxpoints, 1, "Maximum number of points");
+          PML_ADD_FLT(pml, weight0,   1, "Weight at distance 0");
+          PML_ADD_FLT(pml, weightR,   1, "Weight at the search radius");
+          PML_ADD_WORD(pml, radius,   1, "Search radius");
+          PML_ADD_WORD(pml, form,     1, "Form of the curve (linear, exponential, gauss)");
+      
+          int status = pml_read(pml, pargc, pargv);
+          if ( cdoVerbose ) pml_print(pml);
+          if ( status != 0 ) cdoAbort("Parameter read error!");
+          
+          if ( PML_NOCC(pml, nsmooth) )   xnsmooth         = par_nsmooth[0];
+          if ( PML_NOCC(pml, maxpoints) ) spoint.maxpoints = par_maxpoints[0];
+          if ( PML_NOCC(pml, weight0) )   spoint.weight0   = par_weight0[0];
+          if ( PML_NOCC(pml, weightR) )   spoint.weightR   = par_weightR[0];
+          if ( PML_NOCC(pml, radius) )    spoint.radius    = convert_radius(par_radius[0]);
+          if ( PML_NOCC(pml, form) )      spoint.form      = convert_form(par_form[0]);
+
+          UNUSED(nsmooth);
+          UNUSED(maxpoints);
+          UNUSED(radius);
+          UNUSED(form);
+          UNUSED(weight0);
+          UNUSED(weightR);
+
+          pml_destroy(pml);
+        }
+      
+      if ( cdoVerbose )
+        cdoPrint("nsmooth = %d, maxpoints = %d, radius = %gdegree, form = %s, weight0 = %g, weightR = %g",
+                 xnsmooth, spoint.maxpoints, spoint.radius, Form[spoint.form], spoint.weight0, spoint.weightR);
+    }
+
+  spoint.radius *= DEG2RAD;
+
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
+
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
+  vlistDefTaxis(vlistID2, taxisID2);
+
+  int nvars = vlistNvars(vlistID1);
+  int *varIDs = (int*) Malloc(nvars*sizeof(int)); 
+  
+  for ( varID = 0; varID < nvars; ++varID )
+    {
+      int gridID = vlistInqVarGrid(vlistID1, varID);
+      int gridtype = gridInqType(gridID);
+      if ( gridtype == GRID_GAUSSIAN ||
+           gridtype == GRID_LONLAT   ||
+           gridtype == GRID_CURVILINEAR )
+	{
+	  varIDs[varID] = 1;
+	}
+      else if ( gridtype == GRID_UNSTRUCTURED && operatorID == SMOOTH )
+        {
+	  varIDs[varID] = 1;
+        }
+      else
+	{
+          char varname[CDI_MAX_NAME];
+          vlistInqVarName(vlistID1, varID, varname);
+	  varIDs[varID] = 0;
+	  cdoWarning("Unsupported grid for variable %s", varname);
+	}
+    }
+
+  size_t gridsize = vlistGridsizeMax(vlistID1);
+  double *array1 = (double*) Malloc(gridsize*sizeof(double));
+  double *array2 = (double*) Malloc(gridsize*sizeof(double));
+ 
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+
+  streamDefVlist(streamID2, vlistID2);
+
+  int tsID = 0;
+  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+    {
+      taxisCopyTimestep(taxisID2, taxisID1);
+      streamDefTimestep(streamID2, tsID);
+
+      for ( int recID = 0; recID < nrecs; recID++ )
+	{
+	  streamInqRecord(streamID1, &varID, &levelID);
+	  streamReadRecord(streamID1, array1, &nmiss);
+	
+	  if ( varIDs[varID] )
+	    {	    
+	      double missval = vlistInqVarMissval(vlistID1, varID);
+	      int gridID = vlistInqVarGrid(vlistID1, varID);
+
+              for ( int i = 0; i < xnsmooth; ++i )
+                {
+                  if ( operatorID == SMOOTH )
+                    smooth(gridID, missval, array1, array2, &nmiss, spoint);
+                  else if ( operatorID == SMOOTH9 )
+                    smooth9(gridID, missval, array1, array2, &nmiss);
+
+                  memcpy(array1, array2, gridsize*sizeof(double));
+                }
+          
+	      streamDefRecord(streamID2, varID, levelID);
+	      streamWriteRecord(streamID2, array2, nmiss);		
+	    }     	   
+	  else 
+	    {
+	      streamDefRecord(streamID2, varID, levelID);
+	      streamWriteRecord(streamID2, array1, nmiss);
+	    }
+	}
+
+      tsID++;
+    }
+
+  streamClose(streamID2);
+  streamClose(streamID1);
+
+  Free(varIDs);
+  if ( array2 ) Free(array2);
+  if ( array1 ) Free(array1);
+
+  cdoFinish();
+
+  return 0;
+}
diff --git a/src/Smooth9.c b/src/Smooth9.c
deleted file mode 100644
index 53c44df..0000000
--- a/src/Smooth9.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
-  This file is part of CDO. CDO is a collection of Operators to
-  manipulate and analyse Climate model Data.
-
-  Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.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.
-*/
-
-/*
-   This module contains the following operators:
-
-      Smoothstat       smooth9             running 9-point-average
-*/
-
-
-#include <cdi.h>
-#include "cdo.h"
-#include "cdo_int.h"
-#include "pstream.h"
-
-void *Smooth9(void *argument)
-{
-  int operatorID;
-  int streamID1, streamID2;
-  int gridsize;
-  int gridID;
-  int nrecs, recID;
-  int tsID;
-  int varID, levelID;
-  int vlistID1, vlistID2;
-  int nmiss, nmiss2;
-  int i, j , i2;
-  double avg,divavg;
-  double missval1, missval2;
-  double *array1, *array2;
-  int taxisID1, taxisID2;
-  int nlon, nlat;
-  int gridtype;
-  int nvars;
-  int grid_is_cyclic;
-  int *varIDs = NULL, *mask =  NULL; 
-
-  cdoInitialize(argument);
-
-  cdoOperatorAdd("smooth9",   0,   0, NULL);
- 
-  operatorID = cdoOperatorID();
-  UNUSED(operatorID);
-
-  streamID1 = streamOpenRead(cdoStreamName(0));
-
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
-
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
-  vlistDefTaxis(vlistID2, taxisID2);
-
-  nvars = vlistNvars(vlistID1);
-  varIDs  = (int*) Malloc(nvars*sizeof(int)); 
-
-  for ( varID = 0; varID < nvars; ++varID )
-    {
-      gridID = vlistInqVarGrid(vlistID1, varID);
-      gridtype = gridInqType(gridID);
-      if ( gridtype == GRID_GAUSSIAN ||
-           gridtype == GRID_LONLAT   ||
-           gridtype == GRID_CURVILINEAR )
-	{
-	  varIDs[varID] = 1;
-	}
-      else
-	{
-	  varIDs[varID] = 0;
-	  cdoWarning("Unsupported grid for varID %d", varID);
-	}
-    }
-
-  gridsize = vlistGridsizeMax(vlistID1);
-  array1 = (double*) Malloc(gridsize*sizeof(double));
-  array2 = (double*) Malloc(gridsize *sizeof(double));
-  mask   = (int*) Malloc(gridsize *sizeof(int));
- 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
-
-  streamDefVlist(streamID2, vlistID2);
-
-  tsID = 0;
-  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
-    {
-      taxisCopyTimestep(taxisID2, taxisID1);
-
-      streamDefTimestep(streamID2, tsID);
-
-      for ( recID = 0; recID < nrecs; recID++ )
-	{
-	  streamInqRecord(streamID1, &varID, &levelID);
-	  streamReadRecord(streamID1, array1, &nmiss);
-	
-	  if ( varIDs[varID] )
-	    {	    
-	      missval1 = vlistInqVarMissval(vlistID1, varID);
-	      missval2 = missval1;
-
-	      gridID = vlistInqVarGrid(vlistID1, varID);
-	      gridsize = gridInqSize(gridID);
-	      nlon = gridInqXsize(gridID);	 
-	      nlat = gridInqYsize(gridID);
-	      grid_is_cyclic = gridIsCircular(gridID);
-	   
-	      for ( i = 0; i < gridsize; i++) 
-		{		
-		  if ( DBL_IS_EQUAL(missval1, array1[i]) ) mask[i] = 0;
-		  else mask[i] = 1;
-		}
- 
-	      nmiss2=0;
-	      for ( i = 0; i < nlat; i++ )
-		{
-		  for ( i2 = 0; i2 < nlon; i2++ )
-		    {		      
-		      avg = 0; divavg = 0; 	  		     			
-
-		      if ( ( i == 0 ) || ( i2 == 0 )  ||
-                           ( i == ( nlat - 1 ) ) || ( i2 == ( nlon -1 ) ) )
-			{
-			  j = i2+nlon*i;
-			  if ( mask[j] )
-			    {
-			      avg += array1[j];  divavg+= 1;					     		       
-			      /* upper left corner */
-			      if ( (  i!=0 ) && ( i2!=0 ) ) 
-				{ 
-				  j = ((i-1)*nlon)+i2-1;
-				  if ( mask[j] ) 
-				    { avg +=   0.3*array1[j]; divavg+=0.3;}
-				}
-			      else if ( i != 0 && grid_is_cyclic ) 
-				{ 
-				  j = (i-1)*nlon+i2-1+nlon;
-				  if ( mask[j] ) 
-				    { avg+=0.3*array1[j]; divavg+=0.3;}
-				}
-			      
-			      /* upper cell */
-			      if ( i!=0 ) 
-				{
-				  j = ((i-1)*nlon)+i2;
-				  if ( mask[j] )
-				    { avg +=  0.5*array1[j];  divavg+= 0.5; }
-				}
-			      
-			      /* upper right corner */
-			      if ( ( i!=0) && ( i2!=(nlon-1) ) ) 
-				{
-				  j = ((i-1)*nlon)+i2+1;
-				  if ( mask[j] )
-				    { avg +=   0.3*array1[j]; divavg+= 0.3; }
-				}
-			      else if ( i!= 0 && grid_is_cyclic )
-				{ 
-				  j = (i-1)*nlon+i2+1-nlon;
-				  if ( mask[j] ) 
-				    {avg+=0.3*array1[j]; divavg+=0.3;}
-				}
-			      
-			      /* left cell */
-			      if  ( i2!=0 ) 
-				{
-				  j = ((i)*nlon)+i2-1;
-				  if ( mask[j] )
-				    {  avg +=   0.5*array1[j];  divavg+= 0.5;}
-				}
-			      else if ( grid_is_cyclic )
-				{
-				  j = i*nlon-1+nlon;
-				  if ( mask[j] ) 
-				    { avg+=0.5*array1[j]; divavg+=0.5;}
-				}
-			      
-			      /* right cell */
-			      if ( i2!=(nlon-1) ) 
-				{ 
-				  j = (i*nlon)+i2+1;
-				  if ( mask[j] )
-				    {  avg +=   0.5*array1[j]; divavg+= 0.5; } 
-				}
-			      else if ( grid_is_cyclic )
-				{
-				  j = i*nlon+i2+1-nlon;
-				  if (mask[j])
-				    { avg+=0.5*array1[j]; divavg+=0.5;}
-				}
-			      
-			      /* lower left corner */
-			      if ( mask[j] &&  ( (i!=(nlat-1))&& (i2!=0) ) )
-				{	       
-				  j = ((i+1)*nlon+i2-1);
-				  if ( mask[j] )
-				    { avg +=   0.3*array1[j];  divavg+= 0.3; }
-				}
-			      else if ( i!= nlat-1 && grid_is_cyclic ) 
-				{
-				  j= (i+1)*nlon-1+nlon; 
-				  if ( mask[j] ) 
-				    { avg+= 0.3*array1[j]; divavg+=0.3; }
-				}
-			      
-			      /* lower cell */
-			      if  ( i!=(nlat-1) ) 
-				{
-				  j = ((i+1)*nlon)+i2;
-				  if ( mask[j] ) 
-				    { avg += 0.5*array1[j];  divavg+= 0.5;  }
-				}
-			      
-			      /* lower right corner */
-			      if ( i!=(nlat-1) && (i2!=(nlon-1) ) )
-				{
-				  j = ((i+1)*nlon)+i2+1;
-				  if ( mask[j] )
-				    {  avg += 0.3*array1[j]; divavg+= 0.3; }	
-				}
-			      else if ( i != (nlat-1) && grid_is_cyclic )
-				{
-				  j= ((i+1)*nlon)+i2+1-nlon;
-				  if ( mask[j] )
-				    {avg+=0.3*array1[j]; divavg+=0.3;}
-				}
-			    }
-			}
-		      else if ( mask[i2+nlon*i] )
-			{			 
-			  avg += array1[i2+nlon*i]; divavg+= 1;
-			    
-			  j = ((i-1)*nlon)+i2-1;
-			  if ( mask[j] )
-			    { avg += 0.3*array1[j]; divavg+= 0.3; }
-
-			  j = ((i-1)*nlon)+i2;
-			  if ( mask[j] )
-			    { avg += 0.5*array1[j]; divavg+= 0.5; }
-
-			  j = ((i-1)*nlon)+i2+1;
-			  if ( mask[j] )
-			    { avg += 0.3*array1[j]; divavg+= 0.3; }
-
-			  j = ((i)*nlon)+i2-1;
-			  if ( mask[j] )
-			    { avg += 0.5*array1[j]; divavg+= 0.5; }
-
-			  j = (i*nlon)+i2+1;
-			  if ( mask[j] )
-			    { avg += 0.5*array1[j]; divavg+= 0.5; } 
-
-			  j = ((i+1)*nlon+i2-1);	        
-			  if ( mask[j] )
-			    { avg += 0.3*array1[j]; divavg+= 0.3; }
-
-			  j = ((i+1)*nlon)+i2;
-			  if ( mask[j] )
-			    { avg += 0.5*array1[j]; divavg+= 0.5; }
-
-			  j = ((i+1)*nlon)+i2+1;
-			  if ( mask[j] )
-			    { avg += 0.3*array1[j]; divavg+= 0.3; }
-			}
-
-		      if ( fabs(divavg) > 0 )
-			{
-			  array2[i*nlon+i2] = avg/divavg;			
-			}
-		      else 
-			{
-			  array2[i*nlon+i2] = missval2;					
-			  nmiss2++;
-			}
-		    }			    	     
-		}    
-	      streamDefRecord(streamID2, varID, levelID);
-	      streamWriteRecord(streamID2, array2, nmiss2);		
-	    }     	   
-	  else 
-	    {
-	      streamDefRecord(streamID2, varID, levelID);
-	      streamWriteRecord(streamID2, array1, nmiss);
-	    }
-	}
-      tsID++;
-    }
-
-  streamClose(streamID2);
-  streamClose(streamID1);
-
-  Free(varIDs);
-  if ( array2 ) Free(array2);
-  if ( array1 ) Free(array1);
-
-  cdoFinish();
-
-  return 0;
-}
diff --git a/src/Spectral.c b/src/Spectral.c
index 525ef47..11b00c2 100644
--- a/src/Spectral.c
+++ b/src/Spectral.c
@@ -38,14 +38,9 @@
 
 void *Spectral(void *argument)
 {
-  int GP2SP, GP2SPL, SP2GP, SP2GPL, SP2SP, SPCUT;
-  int operatorID;
-  int streamID1, streamID2;
   int nrecs, nvars;
-  int tsID, recID, varID, levelID;
-  int gridsize;
-  int index, ngrids;
-  int vlistID1, vlistID2;
+  int varID, levelID;
+  int index;
   int gridIDsp = -1, gridIDgp = -1;
   int gridID1 = -1, gridID2 = -1;
   int gridID;
@@ -53,36 +48,34 @@ void *Spectral(void *argument)
   int ncut = 0;
   int *wnums = NULL, *waves = NULL;
   int *vars;
-  int lcopy = FALSE;
-  double *array1 = NULL, *array2 = NULL;
-  int taxisID1, taxisID2;
+  double *array2 = NULL;
   int nlon, nlat, ntr;
   SPTRANS *sptrans = NULL;
   LIST *ilist = listNew(INT_LIST);
 
   cdoInitialize(argument);
 
-  GP2SP  = cdoOperatorAdd("gp2sp",  0, 0, NULL);
-  GP2SPL = cdoOperatorAdd("gp2spl", 0, 0, NULL);
-  SP2GP  = cdoOperatorAdd("sp2gp",  0, 0, NULL);
-  SP2GPL = cdoOperatorAdd("sp2gpl", 0, 0, NULL);
-  SP2SP  = cdoOperatorAdd("sp2sp",  0, 0, NULL);
-  SPCUT  = cdoOperatorAdd("spcut",  0, 0, NULL);
+  bool lcopy = UNCHANGED_RECORD;
 
-  operatorID = cdoOperatorID();
+  int GP2SP  = cdoOperatorAdd("gp2sp",  0, 0, NULL);
+  int GP2SPL = cdoOperatorAdd("gp2spl", 0, 0, NULL);
+  int SP2GP  = cdoOperatorAdd("sp2gp",  0, 0, NULL);
+  int SP2GPL = cdoOperatorAdd("sp2gpl", 0, 0, NULL);
+  int SP2SP  = cdoOperatorAdd("sp2sp",  0, 0, NULL);
+  int SPCUT  = cdoOperatorAdd("spcut",  0, 0, NULL);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  int operatorID = cdoOperatorID();
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  ngrids = vlistNgrids(vlistID1);
+  int ngrids = vlistNgrids(vlistID1);
   /* find first spectral grid */
   for ( index = 0; index < ngrids; index++ )
     {
@@ -238,12 +231,12 @@ void *Spectral(void *argument)
 
   if ( gridID1 != -1 ) vlistChangeGrid(vlistID2, gridID1, gridID2);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  gridsize = vlistGridsizeMax(vlistID1);
-  array1 = (double*) Malloc(gridsize*sizeof(double));
+  int gridsize = vlistGridsizeMax(vlistID1);
+  double *array1 = (double*) Malloc(gridsize*sizeof(double));
 
   if ( gridID2 != -1 )
     {
@@ -251,14 +244,14 @@ void *Spectral(void *argument)
       array2 = (double*) Malloc(gridsize*sizeof(double));
     }
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
 
       streamDefTimestep(streamID2, tsID);
 	       
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID, &levelID);
 
@@ -294,6 +287,7 @@ void *Spectral(void *argument)
 		}
 	    }    
 	}
+
       tsID++;
     }
 
diff --git a/src/Split.c b/src/Split.c
index b55743b..b807e6d 100644
--- a/src/Split.c
+++ b/src/Split.c
@@ -60,7 +60,6 @@ void *Split(void *argument)
   int nsplit = 0;
   int index;
   int i;
-  int lcopy = FALSE;
   int gridsize;
   int nmiss;
   int swap_obase = FALSE;
@@ -70,6 +69,8 @@ void *Split(void *argument)
 
   if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
 
+  bool lcopy = UNCHANGED_RECORD;
+
   int SPLITCODE   = cdoOperatorAdd("splitcode",   0, 0, NULL);
   int SPLITPARAM  = cdoOperatorAdd("splitparam",  0, 0, NULL);
   int SPLITNAME   = cdoOperatorAdd("splitname",   0, 0, NULL);
@@ -89,8 +90,6 @@ void *Split(void *argument)
       else cdoAbort("Unknown parameter: >%s<", operatorArgv()[0]); 
     }
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
-
   int streamID1 = streamOpenRead(cdoStreamName(0));
 
   int vlistID1 = streamInqVlist(streamID1);
diff --git a/src/Splitrec.c b/src/Splitrec.c
index f1d9371..d5755a2 100644
--- a/src/Splitrec.c
+++ b/src/Splitrec.c
@@ -29,18 +29,12 @@
 
 void *Splitrec(void *argument)
 {
-  int nchars;
-  int streamID1, streamID2;
   int varID;
-  int nrecs;
-  int tsID, recID, levelID;
+  int recID, levelID;
   int varID2, levelID2;
-  int vlistID1, vlistID2;
   char filesuffix[32];
   char filename[8192];
   const char *refname;
-  int index;
-  int lcopy = FALSE;
   int gridsize;
   int nmiss;
   double *array = NULL;
@@ -49,16 +43,16 @@ void *Splitrec(void *argument)
 
   if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
+  int vlistID1 = streamInqVlist(streamID1);
 
-  nrecs  = vlistNrecs(vlistID1);
+  int nrecs  = vlistNrecs(vlistID1);
 
   strcpy(filename, cdoStreamName(1)->args);
-  nchars = strlen(filename);
+  int nchars = strlen(filename);
 
   refname = cdoStreamName(0)->argv[cdoStreamName(0)->argc-1];
   filesuffix[0] = 0;
@@ -71,8 +65,8 @@ void *Splitrec(void *argument)
       array = (double*) Malloc(gridsize*sizeof(double));
     }
 
-  index = 0;
-  tsID = 0;
+  int index = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       for ( recID = 0; recID < nrecs; recID++ )
@@ -82,7 +76,7 @@ void *Splitrec(void *argument)
 	  vlistClearFlag(vlistID1);
 	  vlistDefFlag(vlistID1, varID, levelID, TRUE);
 
-	  vlistID2 = vlistCreate();
+	  int vlistID2 = vlistCreate();
 	  vlistCopyFlag(vlistID2, vlistID1);
 
 	  index++;
@@ -93,7 +87,7 @@ void *Splitrec(void *argument)
 	  if ( cdoVerbose ) cdoPrint("create file %s", filename);
 
 	  argument_t *fileargument = file_argument_new(filename);
-	  streamID2 = streamOpenWrite(fileargument, cdoFiletype());
+	  int streamID2 = streamOpenWrite(fileargument, cdoFiletype());
 	  file_argument_free(fileargument);
 
 	  streamDefVlist(streamID2, vlistID2);
diff --git a/src/Splitsel.c b/src/Splitsel.c
index 71681f7..9c772c3 100644
--- a/src/Splitsel.c
+++ b/src/Splitsel.c
@@ -35,12 +35,9 @@ void *Splitsel(void *argument)
   int varID, levelID, recID;
   int tsID, tsID2;
   int nsets;
-  int streamID1, streamID2;
-  int vlistID1, vlistID2, taxisID1, taxisID2;
   int nmiss;
   int gridID;
-  int nvars, nlevel;
-  int nconst;
+  int nlevel;
 /*   int ndates = 0, noffset = 0, nskip = 0, nargc; */
   double ndates, noffset, nskip;
   int i2 = 0;
@@ -52,7 +49,6 @@ void *Splitsel(void *argument)
   char filename[8192];
   const char *refname;
   int index = 0;
-  int lcopy = FALSE;
   double *array = NULL;
   field_t **vars = NULL;
 
@@ -60,9 +56,9 @@ void *Splitsel(void *argument)
 
   if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
 
-  cdoOperatorAdd("splitsel",  0,  0, NULL);
+  bool lcopy = UNCHANGED_RECORD;
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  cdoOperatorAdd("splitsel",  0,  0, NULL);
 
   /*  operatorInputArg("nsets <noffset <nskip>>"); */
 
@@ -82,14 +78,14 @@ void *Splitsel(void *argument)
 
   if ( cdoVerbose ) cdoPrint("nsets = %f, noffset = %f, nskip = %f", ndates, noffset, nskip);
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
 /*   taxisID2 = taxisCreate(TAXIS_ABSOLUTE); */
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
   strcpy(filename, cdoStreamName(1)->args);
@@ -106,8 +102,8 @@ void *Splitsel(void *argument)
       array = (double*) Malloc(gridsize*sizeof(double));
     }
 
-  nvars = vlistNvars(vlistID1);
-  nconst = 0;
+  int nvars = vlistNvars(vlistID1);
+  int nconst = 0;
   for ( varID = 0; varID < nvars; varID++ )
     if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) nconst++;
 
@@ -167,7 +163,7 @@ void *Splitsel(void *argument)
 	  
       if ( cdoVerbose ) cdoPrint("create file %s", filename);
       argument_t *fileargument = file_argument_new(filename);
-      streamID2 = streamOpenWrite(fileargument, cdoFiletype());
+      int streamID2 = streamOpenWrite(fileargument, cdoFiletype());
       file_argument_free(fileargument);
 
       streamDefVlist(streamID2, vlistID2);
diff --git a/src/Splittime.c b/src/Splittime.c
index d7cdc6e..5d7cb7b 100644
--- a/src/Splittime.c
+++ b/src/Splittime.c
@@ -65,7 +65,6 @@ void *Splittime(void *argument)
   int index = 0;
   int i;
   int vdate, vtime;
-  int lcopy = FALSE;
   int gridsize;
   int nmiss;
   int gridID;
@@ -78,7 +77,7 @@ void *Splittime(void *argument)
 
   if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
   int SPLITHOUR = cdoOperatorAdd("splithour", func_time, 10000, NULL);
   int SPLITDAY  = cdoOperatorAdd("splitday",  func_date,     1, NULL);
diff --git a/src/Splityear.c b/src/Splityear.c
index bf1333f..5810466 100644
--- a/src/Splityear.c
+++ b/src/Splityear.c
@@ -22,6 +22,8 @@
      Splityear  splityearmon    Split in years and month
 */
 
+#include <limits.h>
+
 #include <cdi.h>
 #include "cdo.h"
 #include "cdo_int.h"
@@ -42,7 +44,6 @@ void *Splityear(void *argument)
   int day;
   int year1, year2;
   int mon1, mon2;
-  int lcopy = FALSE;
   int gridsize;
   int ic = 0;
   int cyear[MAX_YEARS];
@@ -55,8 +56,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;
+  
+  bool lcopy = UNCHANGED_RECORD;
 
   int SPLITYEAR    = cdoOperatorAdd("splityear",     0, 10000, NULL);
   int SPLITYEARMON = cdoOperatorAdd("splityearmon",  0,   100, NULL);
@@ -118,7 +119,7 @@ void *Splityear(void *argument)
 	}
     }
 
-  int index1 = - 1<<31;
+  int index1 = -INT_MAX;
   int index2;
   year1 = -1;
   mon1  = -1;
diff --git a/src/Tee.c b/src/Tee.c
index 73c3990..9543175 100644
--- a/src/Tee.c
+++ b/src/Tee.c
@@ -23,33 +23,27 @@
 
 void *Tee(void *argument)
 {
-  int streamID1, streamID2, streamID3;
   int nrecs;
-  int tsID, recID, varID, levelID;
-  int lcopy = FALSE;
-  int gridsize;
-  int vlistID1, vlistID2, vlistID3;
+  int varID, levelID;
   int nmiss;
-  int taxisID1, taxisID2, taxisID3;
-  double *array = NULL;
 
   cdoInitialize(argument);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  taxisID1 = vlistInqTaxis(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
-  streamID3 = streamOpenWrite(cdoStreamName(2), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID3 = streamOpenWrite(cdoStreamName(2), cdoFiletype());
 
-  vlistID2 = vlistDuplicate(vlistID1);
-  vlistID3 = vlistDuplicate(vlistID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID3 = vlistDuplicate(vlistID1);
 
-  taxisID2 = taxisDuplicate(taxisID1);
-  taxisID3 = taxisDuplicate(taxisID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID3 = taxisDuplicate(taxisID1);
 
   vlistDefTaxis(vlistID2, taxisID2);
   vlistDefTaxis(vlistID3, taxisID3);
@@ -57,10 +51,10 @@ void *Tee(void *argument)
   streamDefVlist(streamID2, vlistID2);
   streamDefVlist(streamID3, vlistID3);
 
-  gridsize = vlistGridsizeMax(vlistID1);
-  array = (double*) Malloc(gridsize*sizeof(double));
+  int gridsize = vlistGridsizeMax(vlistID1);
+  double *array = (double*) Malloc(gridsize*sizeof(double));
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
@@ -69,7 +63,7 @@ void *Tee(void *argument)
       streamDefTimestep(streamID2, tsID);
       streamDefTimestep(streamID3, tsID);
 	       
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{ 
 	  if ( lcopy )
 	    {
diff --git a/src/Templates.c b/src/Templates.c
index 1a1b57f..f67f32c 100644
--- a/src/Templates.c
+++ b/src/Templates.c
@@ -24,13 +24,12 @@
 void *Template1(void *argument)
 {
   int nrecs;
-  int recID, varID, levelID;
-  int lcopy = FALSE;
+  int varID, levelID;
   int gridsize, nmiss;
 
   cdoInitialize(argument);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  bool lcopy = UNCHANGED_RECORD;
 
   int streamID1 = streamOpenRead(cdoStreamName(0));
 
@@ -59,7 +58,7 @@ void *Template1(void *argument)
 
       streamDefTimestep(streamID2, tsID);
 	       
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  streamDefRecord(streamID2,  varID,  levelID);
@@ -94,7 +93,7 @@ void *Template1(void *argument)
 void *Template2(void *argument)
 {
   int nrecs;
-  int recID, varID, levelID;
+  int varID, levelID;
   int nmiss;
 
   cdoInitialize(argument);
@@ -122,7 +121,7 @@ void *Template2(void *argument)
 
       streamDefTimestep(streamID2, tsID);
 	       
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  streamDefRecord(streamID2,  varID,  levelID);
diff --git a/src/Timedt.c b/src/Timedt.c
index 981fea4..7ecfdef 100644
--- a/src/Timedt.c
+++ b/src/Timedt.c
@@ -108,8 +108,8 @@ void *Timedt(void *argument)
       tsID2++;
     }
 
-  free(array1);
-  free(array2);
+  Free(array1);
+  Free(array2);
   field_free(vars, vlistID1);
 
   streamClose(streamID2);
diff --git a/src/Timstat.c b/src/Timstat.c
index 5e21483..4da05e5 100644
--- a/src/Timstat.c
+++ b/src/Timstat.c
@@ -226,7 +226,7 @@ void *Timstat(void *argument)
       streamDefVlist(streamID3, vlistID3);
     }
 
-  recinfo_t *recinfo = (recinfo_t *) malloc(maxrecs*sizeof(recinfo_t));
+  recinfo_t *recinfo = (recinfo_t *) Malloc(maxrecs*sizeof(recinfo_t));
 
   dtlist_type *dtlist = dtlist_new();
   dtlist_set_stat(dtlist, timestat_date);
diff --git a/src/Vargen.c b/src/Vargen.c
index 2a8237a..998f04c 100644
--- a/src/Vargen.c
+++ b/src/Vargen.c
@@ -88,6 +88,50 @@ double std_atm_pressure(double height)
 }
 
 static
+void conv_generic_grid(int gridID, int gridsize, double *xvals2D, double *yvals2D)
+{
+  int xsize = gridInqXsize(gridID);
+  int ysize = gridInqYsize(gridID);
+
+  assert(gridsize==xsize*ysize);
+
+  double *xcoord = (double*) Malloc(xsize*sizeof(double));
+  double *ycoord = (double*) Malloc(ysize*sizeof(double));
+
+  gridInqXvals(gridID, xcoord);
+  gridInqYvals(gridID, ycoord);
+
+  double xmin = xcoord[0];
+  double xmax = xcoord[0];
+  for ( int i = 1; i < xsize; ++i )
+    {
+      if ( xcoord[i] < xmin ) xmin = xcoord[i];
+      if ( xcoord[i] > xmax ) xmax = xcoord[i];
+    }
+
+  double ymin = ycoord[0];
+  double ymax = ycoord[0];
+  for ( int i = 1; i < ysize; ++i )
+    {
+      if ( ycoord[i] < ymin ) ymin = ycoord[i];
+      if ( ycoord[i] > ymax ) ymax = ycoord[i];
+    }
+
+  double xrange = xmax - xmin;
+  double yrange = ymax - ymin;
+  
+  for ( int j = 0; j < ysize; ++j )
+    for ( int i = 0; i < xsize; ++i )
+      {
+        xvals2D[j*xsize+i] = xcoord[i]*M_PI/xrange; 
+        yvals2D[j*xsize+i] = ycoord[j]*M_PI/yrange; 
+      }
+  
+  Free(xcoord);
+  Free(ycoord);
+}
+
+static
 void remap_nn_reg2d_reg2d(int nx, int ny, const double *restrict data, int gridID, double *restrict array)
 {
   if ( !(gridInqType(gridID) == GRID_LONLAT && !gridIsRotated(gridID)) )
@@ -183,6 +227,8 @@ void remap_nn_reg2d(int nx, int ny, const double *restrict data, int gridID, dou
     remap_nn_reg2d_nonreg2d(nx, ny, data, gridID, array);
 }
 
+#define NLON 720
+#define NLAT 360
 
 void *Vargen(void *argument)
 {
@@ -194,9 +240,9 @@ void *Vargen(void *argument)
   double rval, rstart = 0, rstop = 0, rinc = 0;
   double rconst = 0;
   double *levels = NULL;
-  double lon[720], lat[360];
-  int nlon = 720;
-  int nlat = 360;
+  double lon[NLON], lat[NLAT];
+  int nlon = NLON;
+  int nlat = NLAT;
 
   cdoInitialize(argument);
 
@@ -407,21 +453,28 @@ void *Vargen(void *argument)
 		  double *xvals = (double*) Malloc(gridsize*sizeof(double));
 		  double *yvals = (double*) Malloc(gridsize*sizeof(double));
 
-		  if ( gridInqType(gridID) == GRID_GME ) gridID = gridToUnstructured(gridID, 0);
-
-		  if ( gridInqType(gridID) != GRID_UNSTRUCTURED && gridInqType(gridID) != GRID_CURVILINEAR )
-		    gridID = gridToCurvilinear(gridID, 0);
-
-		  gridInqXvals(gridID, xvals);
-		  gridInqYvals(gridID, yvals);
-
-		  /* Convert lat/lon units if required */
-		  char units[CDI_MAX_NAME];
-		  gridInqXunits(gridID, units);
-		  grid_to_radian(units, gridsize, xvals, "grid center lon");
-		  gridInqYunits(gridID, units);
-		  grid_to_radian(units, gridsize, yvals, "grid center lat");
-
+                  if ( grid_is_distance_generic(gridID) )
+                    {
+                      conv_generic_grid(gridID, gridsize, xvals, yvals);
+                    }
+                  else
+                    {
+                      if ( gridInqType(gridID) == GRID_GME ) gridID = gridToUnstructured(gridID, 0);
+
+                      if ( gridInqType(gridID) != GRID_UNSTRUCTURED && gridInqType(gridID) != GRID_CURVILINEAR )
+                        gridID = gridToCurvilinear(gridID, 0);
+
+                      gridInqXvals(gridID, xvals);
+                      gridInqYvals(gridID, yvals);
+
+                      /* Convert lat/lon units if required */
+                      char units[CDI_MAX_NAME];
+                      gridInqXunits(gridID, units);
+                      grid_to_radian(units, gridsize, xvals, "grid center lon");
+                      gridInqYunits(gridID, units);
+                      grid_to_radian(units, gridsize, yvals, "grid center lat");
+                    }
+                  
 		  if ( operatorID == SINCOS )
 		    {
 		      for ( i = 0; i < gridsize; i++ )
diff --git a/src/Verifygrid.c b/src/Verifygrid.c
index 496ffb6..e85be53 100644
--- a/src/Verifygrid.c
+++ b/src/Verifygrid.c
@@ -19,197 +19,192 @@
    This module contains the following operators:
 */
 
-#if defined(HAVE_CONFIG_H)
-#  include "config.h" /* VERSION */
-#endif
-
 #include <cdi.h>
 #include "cdo.h"
 #include "cdo_int.h"
 #include "grid.h"
 #include "pstream.h"
 #include "clipping/geometry.h"
-#include "clipping/clipping.c"
-#include "math.h"
-
-struct axis {
-  double axis_vector[3];
-};
-
-static double Euclidean_norm (double a[]) {
-
-  /* Computes the Euclidean norm of a vector given in Cartesian coordinates. */
-
-  return sqrt(pow(a[0],2) + pow(a[1],2) + pow(a[2],2));
-}
-
-static struct axis divide_by_scalar (struct axis a, double scalar) {
+#include "time.h"
 
-  /* Component-wise scalar division of a three dimensional axis vector given in Cartesian coordinates. */
+/* Quicksort is called with a pointer to the array to be sorted and an integer indicating its length. */
 
-  a.axis_vector[0] = a.axis_vector[0]/scalar;
-  a.axis_vector[1] = a.axis_vector[1]/scalar;
-  a.axis_vector[2] = a.axis_vector[2]/scalar;
-
-  return a;
+void quick_sort(double * array, int array_length) {
+  int i, j;
+  double p, temp;
+  
+  if (array_length < 2)
+    return;
+  p = array[array_length / 2];
+  for (i = 0, j = array_length - 1;; i++, j--) {
+    while (array[i] < p)
+      i++;
+    while (p < array[j])
+      j--;
+    if (i >= j)
+      break;
+    temp = array[i];
+    array[i] = array[j];
+    array[j] = temp;
+  }
+  quick_sort(array, i);
+  quick_sort(array + i, array_length - i);
 }
 
-static struct axis normalize_vector(struct axis a){
-
-  /* Normalizes an axis vector a by dividing it though its magnitude. */
+/* Quicksort is called with a pointer to the array of center points to be sorted and an integer indicating its length. It sorts the array by its longitude coordinates */
 
-  a = divide_by_scalar(a, Euclidean_norm(a.axis_vector));
+void quick_sort_by_lon(double * array, int array_length) {
+  int i, j;
+  double p, temp_lon, temp_lat;
+  
+  if (array_length < 4)
+    return;
+  
+  if((array_length / 2) % 2 != 0){
+    p = array[(array_length / 2) + 1];
+  } else {
+    p = array[array_length / 2];
+  }
+      
+      
+  for (i = 0, j = array_length - 2;; i += 2, j -= 2) {
+    while (array[i] < p)
+      i += 2;
 
-  return a;
+    while (p < array[j])
+      j -= 2;
+    
+    if (i >= j)
+      break;
+    
+    temp_lon = array[i];
+    temp_lat = array[i + 1];
+    array[i] = array[j];
+    array[i + 1] = array[j + 1];
+    array[j] = temp_lon;
+    array[j + 1] = temp_lat;
+  }
+  quick_sort_by_lon(array, i);
+  quick_sort_by_lon(array + i, array_length - i);
 }
 
-static struct axis compute_the_new_z_axis(double cell_corners_in_Euclidean_space[]){
+/* This uses quicksort to sort the latitude coordinates in a subarray of all coordinates. */
 
-  /* Takes the first three corners/vertices of the cell and computes two edges originating at the first corner/vertex. These two edges are on the same plane as all the other vertices. THERE NEED TO BE AT LEAST THREE CORNERS. */
+void quick_sort_of_subarray_by_lat(double * array, int subarray_start, int subarray_end){
 
-  double edge_one[3] = {(cell_corners_in_Euclidean_space)[3 + 0] -(cell_corners_in_Euclidean_space)[0],
-			(cell_corners_in_Euclidean_space)[3 + 1] -(cell_corners_in_Euclidean_space)[1],
-			(cell_corners_in_Euclidean_space)[3 + 2] -(cell_corners_in_Euclidean_space)[2]};
+  int subarray_length = (subarray_end - subarray_start) / 2 + 1;     
+  double subarray[subarray_length];
+  int subarray_index = 0;
   
-  double edge_two[3] = {(cell_corners_in_Euclidean_space)[6 + 0] - (cell_corners_in_Euclidean_space)[0],
-			(cell_corners_in_Euclidean_space)[6 + 1] - (cell_corners_in_Euclidean_space)[1],
-			(cell_corners_in_Euclidean_space)[6 + 2] - (cell_corners_in_Euclidean_space)[2]};
-
-  struct axis new_z_axis;
-
-  /* The cross product of the two edges is the surface normal and the new z-axis. crossproduct_d is defined in clipping/geometry.h */
+  for(int index = subarray_start + 1; index <= subarray_end + 1; index += 2){	 
+    subarray[subarray_index] = array[index];
+    subarray_index += 1;	  
+  }
   
-  crossproduct_d(edge_one, edge_two, new_z_axis.axis_vector);
-
-  new_z_axis = normalize_vector(new_z_axis);
+  quick_sort(subarray, subarray_length);
   
-  return new_z_axis;
-}
-
- 
-static struct axis compute_the_new_y_axis(struct axis new_z_axis){
-
-  /* Then the new y-axis is the result of the cross product of the new z-axis and the old x-axis. crossproduct_d is defined in clipping/geometry.h */
+  subarray_index = 0;
   
-  struct axis old_x_axis;
- 
-  old_x_axis.axis_vector[0] = 1;
-  old_x_axis.axis_vector[1] = 0;
-  old_x_axis.axis_vector[2] = 0;
+  for(int index = subarray_start + 1; index <= subarray_end + 1; index += 2){
+    array[index] = subarray[subarray_index];
+    subarray_index += 1;	  
+  }            
+}
 
-  struct axis new_y_axis;
-  
-  crossproduct_d(new_z_axis.axis_vector, old_x_axis.axis_vector, new_y_axis.axis_vector);
-  
-  new_y_axis = normalize_vector(new_y_axis);
 
-  return new_y_axis;
-}
 
-static struct axis compute_the_new_x_axis(struct axis new_z_axis, struct axis new_y_axis){
 
-  /* The new x-axis is the result of the cross product of the new z-axis and the new y-axis. crossproduct_d is defined in clipping/geometry.h */
+static
+double determinant(double matrix[3][3]){
   
-  struct axis new_x_axis;
-
-  crossproduct_d(new_y_axis.axis_vector, new_z_axis.axis_vector, new_x_axis.axis_vector);
+  /* Calculates the determinant for a 3 x 3 matrix. */
   
-  new_x_axis = normalize_vector(new_x_axis);
-
-  return new_x_axis;
+  return matrix[0][0] * matrix[1][1] * matrix[2][2] 
+    + matrix[0][1] * matrix[1][2] * matrix[2][0] 
+    + matrix[0][2] * matrix[1][0] * matrix[2][1] 
+    - matrix[0][2] * matrix[1][1] * matrix[2][0] 
+    - matrix[0][1] * matrix[1][0] * matrix[2][2] 
+    - matrix[0][0] * matrix[1][2] * matrix[2][1];
 }
 
-static void project_Euclidean_corner_coordinates_onto_the_cell_plane(struct axis new_x_axis, struct axis new_y_axis, double (*p_cell_corners_in_Euclidean_space)[30], double (*p_cell_corners_on_cell_plane)[20], int ncorners){
-
-  /* All corner points are projected onto the new x- and y-axes. dotproduct is defined in clipping/clipping.c */
-
-  double corner_vector[3];
+static
+void find_unit_normal(double a[3], double b[3], double c[3], double * unit_normal){
+  
+  /* Calculates the unit normal for a plane defined on three points a, b, c in Euclidean space. */
 
-  for (int corner_no = 0; corner_no < ncorners; corner_no++){
-    
-    for (int vector_component = 0; vector_component < 3; ++vector_component){
-      corner_vector[vector_component] = (*p_cell_corners_in_Euclidean_space)[(corner_no * 3) + vector_component];
-    }
-    
-    (*p_cell_corners_on_cell_plane)[(corner_no * 2) + 0] = dotproduct(new_x_axis.axis_vector, corner_vector);
-    (*p_cell_corners_on_cell_plane)[(corner_no * 2) + 1] = dotproduct(new_y_axis.axis_vector, corner_vector);  
+  double matrix_for_x[3][3] = {{1, a[1], a[2]},
+			       {1, b[1], b[2]},
+			       {1, c[1], c[2]}			 
+  };
 
-    }
-      
-  /* The last vertex is set to be the same as the first one in order to close the cell.*/
+  double x = determinant(matrix_for_x);
 
-  (*p_cell_corners_on_cell_plane)[(ncorners * 2) + 0] = (*p_cell_corners_on_cell_plane)[0];
-  (*p_cell_corners_on_cell_plane)[(ncorners * 2) + 1] = (*p_cell_corners_on_cell_plane)[1];
+  double matrix_for_y[3][3] = {{a[0], 1, a[2]},
+			       {b[0], 1, b[2]},
+			       {c[0], 1, c[2]}
+  };
+  
+  double y = determinant(matrix_for_y);
   
-  /*
-  printf("The coordinates of the cell vertices on the cell plane are: ");
+  double matrix_for_z[3][3] = {{a[0], a[1], 1},
+			       {b[0], b[1], 1},
+			       {c[0], c[1], 1}
+  };
 
-  for (int corner_no =0; corner_no <= ncorners; corner_no++){
-    printf("(%f, %f) ", cell_corners_on_cell_plane[(corner_no * 2) + 0], cell_corners_on_cell_plane[(corner_no * 2) + 1]);
-  }
+  double z = determinant(matrix_for_z);
 
-  printf("\n\n");
-  */
-}
+  double magnitude = sqrt(x * x + y * y + z * z);
 
-static void project_Euclidean_center_coordinates_onto_the_cell_plane(struct axis new_x_axis, struct axis new_y_axis, double (*p_center_point_in_Euclidean_space)[3], double (*p_center_point_on_cell_plane)[2]){
-  
-  /* The center point is projected onto the new x- and -y-axes. dotproduct is defined in clipping/clipping.c  */
+  unit_normal[0] = x / magnitude;
+  unit_normal[1] = y / magnitude;
+  unit_normal[2] = z / magnitude;
 
-  (*p_center_point_on_cell_plane)[0] = dotproduct((new_x_axis.axis_vector), (*p_center_point_in_Euclidean_space));
-  (*p_center_point_on_cell_plane)[1] = dotproduct((new_y_axis.axis_vector), (*p_center_point_in_Euclidean_space));
-  
-  /*
-  printf("The coordinates of the presumed center point of the cell on the cell plane are: (%f, %f)\n\n", (*p_center_point_on_cell_plane)[0], (*p_center_point_on_cell_plane)[1]);
-  */
 }
 
-static double is_point_left_of_edge(double point_on_line_1[2], double point_on_line_2[2], double point[2]){
-
-  /* 
-     Computes whether a point is left of the line through point_on_line_1 and point_on_line_2. This is part of the solution to the point in polygon problem.
-     Returns 0 if the point is on the line, > 0 if the point is left of the line, and < 0 if the point is right of the line.
-     This algorithm is by Dan Sunday (geomalgorithms.com) and is completely free for use and modification.
-  */
+static
+int no_of_duplicates_in_this_list_of_vertices(double cell_corners[], int array_length)
+{
+  /* Returns the number of coordinate duplicates found in a list of Cartesian coordinates, the cell corners or vertices. */
   
-  /*
-  printf("Testing whether point (%f, %f) is left of the the edge from point (%f, %f) and point (%f, %f)... ", point[0], point[1], point_on_line_1[0], point_on_line_1[1], point_on_line_2[0], point_on_line_2[1]);
-  */
-  double answer = ((point_on_line_2[0] - point_on_line_1[0]) * (point[1] - point_on_line_1[1]) 
-		- (point[0] - point_on_line_1[0]) * (point_on_line_2[1] - point_on_line_1[1]));
+  /* Ensure that the lenght of the array is a multiple of 3. */
 
-  if (answer == 0){
-    printf("the point lies on the edge.\n");
+  if ((array_length % 3) != 0){
+    return -1;
   }
 
-  if (answer > 0){
-    printf("the point lies left of the edge.\n");
-  }
+  /* A brute force search for duplicate Cartesian coordinates. */
 
-  if (answer < 0){
-    printf("the point lies to the right of the edge.\n");
-  }
+  int no_duplicates = 0;
 
-  return answer;
+  for (int i = 0; i < array_length; i = i + 3){
+    for (int j = i + 3; j < array_length; j = j + 3 ){
+      if ( IS_EQUAL(cell_corners[i + 0], cell_corners[j])     &&
+           IS_EQUAL(cell_corners[i + 1], cell_corners[j + 1]) &&
+           IS_EQUAL(cell_corners[i + 2], cell_corners[j + 2]) ){
+	    no_duplicates += 1;
+      }
+    }
+  }
+  return no_duplicates;
 }
 
-static double is_point_left_of_edge_without_printfs(double point_on_line_1[2], double point_on_line_2[2], double point[2]){
-
+static
+double is_point_left_of_edge(double point_on_line_1[2], double point_on_line_2[2], double point[2])
+{
   /* 
      Computes whether a point is left of the line through point_on_line_1 and point_on_line_2. This is part of the solution to the point in polygon problem.
      Returns 0 if the point is on the line, > 0 if the point is left of the line, and < 0 if the point is right of the line.
      This algorithm is by Dan Sunday (geomalgorithms.com) and is completely free for use and modification.
   */
   
-  /*
-  printf("Testing whether point (%f, %f) is left of the the edge from point (%f, %f) and point (%f, %f)... ", point[0], point[1], point_on_line_1[0], point_on_line_1[1], point_on_line_2[0], point_on_line_2[1]);
-  */
   double answer = ((point_on_line_2[0] - point_on_line_1[0]) * (point[1] - point_on_line_1[1]) 
 		- (point[0] - point_on_line_1[0]) * (point_on_line_2[1] - point_on_line_1[1]));
+  
   return answer;
 }
 
-static int winding_numbers_algorithm_without_printfs(double cell_corners[], int number_corners, double point[]){
+static
+int winding_numbers_algorithm(double cell_corners[], int number_corners, double point[]){
   
   /* 
      Computes whether a point is inside the bounds of a cell. This is the solution to the point in polygon problem.
@@ -219,14 +214,14 @@ static int winding_numbers_algorithm_without_printfs(double cell_corners[], int
   
   int winding_number = 0;
   
-  for (int i = 0;  i < number_corners; i++){
+  for (int i = 0;  i < number_corners - 1; i++){
     if (cell_corners[i * 2 + 1] <= point[1]){
       if (cell_corners[(i + 1) * 2 + 1] > point[1]){
 	
 	double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
 	double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
 
-	if (is_point_left_of_edge_without_printfs(point_on_edge_1, point_on_edge_2, point) > 0){
+	if (is_point_left_of_edge(point_on_edge_1, point_on_edge_2, point) > 0){
 	  winding_number++;
 	}
       }       
@@ -237,865 +232,455 @@ static int winding_numbers_algorithm_without_printfs(double cell_corners[], int
 	double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
 	double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
 
-	if (is_point_left_of_edge_without_printfs(point_on_edge_1, point_on_edge_2, point) < 0){
-	  winding_number--;
-	}
-      }
-    }
-  }
-  return winding_number;
-}
-
-static int winding_numbers_algorithm_with_printfs(double cell_corners[], int number_corners, double point[]){
-  
-  /* 
-     Computes whether a point is inside the bounds of a cell. This is the solution to the point in polygon problem.
-     Returns 0 if the point is outside, returns 1 if the point is inside the cell.
-     Based on an algorithm by Dan Sunday (geomalgorithms.com). His algorithm is completely free for use and modification.
-  */
-
-  printf("Checking if the presumed center point lies within the bounds of the cell ... \n\n");
-  
-  int winding_number = 0;
-  
-  for (int i = 0;  i < number_corners; i++){
-    printf("Edge number %u from vertex (%f, %f) to vertex (%f, %f):\n\n", i+1, cell_corners[i * 2 + 0], cell_corners[i * 2 + 1], cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]);
-    if (cell_corners[i * 2 + 1] <= point[1]){
-      if (cell_corners[(i + 1) * 2 + 1] > point[1]){
-	printf("There is an upward crossing of the ray y = %f.\n", point[1]);
-
-	double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
-	double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
-
-	if (is_point_left_of_edge(point_on_edge_1, point_on_edge_2, point) > 0){
-	  winding_number++;
-	  printf("The upward edge crossing happened on the right side of the presumed center point. The new winding number is increased to  %u.\n", winding_number);
-	}
-	else {
-	  printf("The downward edge crossing happened on the left side of the presumed center point. The winding number remains unchanged.\n");
-	}
-      } 
-      else {
-	printf("There is NO crossing of the ray y = %f.\n", point[1]);
-      }
-    }
-    else { 
-      if (cell_corners[(i + 1) * 2 + 1] <= point[1]){
-	printf("There is a downward crossing of the ray y = %f.\n", point[1]);
-
-	double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
-	double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
-
 	if (is_point_left_of_edge(point_on_edge_1, point_on_edge_2, point) < 0){
 	  winding_number--;
-	  printf("The downward edge crossing happened on the right side of the presumed center point. The new winding number is decreased to %u.\n", winding_number);
-	}
-	else {
-	  printf("The downward edge crossing happened on the left side of the presumed center point. The winding number remains unchanged.\n");
 	}
       }
-      else {
-	printf("There is NO crossing of the ray y = %f.\n", point[1]);
-      }
     }
-    printf("\n");
   }
   return winding_number;
 }
 
-static double perp_dot_product(double vector_one[2], double vector_two[2]){
-
-  /* 
-     The perp-dot product is used for testing if a simple polygon is convex. From Hill, F. S. Jr. "The Pleasures of 'Perp Dot' Products." Chapter II.5 in Graphics Gems IV, Academic Press, 1994
-     It uses a vector that is perpendicular to vector_one (rotated 90 degrees counterclockwise) to calculate the dot product with vector_two.
-     It is positive if vector_one is less than 90 degrees away from vector_two indicating a left turn between vector_one and vector_two, and is negative otherwise.
-     If all edges of a simple polygon wind the same way, it is convex.
-  */
-  
-  return (vector_one[0] * vector_two[1]) - (vector_one[1] - vector_two[0]);
-
-}
-
-static double sign(double x){
-
+static
+double sign(double x)
+{
   /* Is +1 if x is positive, -1 if x is negative and 0 if x is zero.*/
 
   return (x > 0) -  (x < 0);
 }
 
+static
+bool is_simple_polygon_convex(double cell_corners[], int number_corners){
 
-static int is_simple_polygon_convex(double cell_corners[], int number_corners){
-
-  /* Uses the perp-dot product to tell if a simple polygon, a cell, is convex. */
+   /* Tests in which direction the polygon winds when walking along its edges. Does so for all edges of the polygon. */
 
   double direction = 0;
-
-  for (int i = 0; i < number_corners - 1; i++){
-
-    /* Tests in which direction edge B winds that is connected to edge A when walking along the polygon edges. Does so for all edges of the polygon. */
-
-    double edge_a[2] = {cell_corners[(i + 1) * 2 + 0] - cell_corners[i * 2 + 0], cell_corners[(i + 1) * 2 + 1] - cell_corners[i * 2 + 1]};
-    double edge_b[2] = {cell_corners[(i + 2) * 2 + 0] - cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 2) * 2 + 1] - cell_corners[(i + 1) * 2 + 1]};
-    
-    double turns_to = sign(perp_dot_product(edge_a, edge_b));
+  
+  for ( int i = 0; i < number_corners - 2; i++ ){
     
+    double turns_to = (cell_corners[i * 2 + 0] - cell_corners[(i + 1) * 2 + 0]) 
+      * (cell_corners[(i + 1) * 2 + 1] - cell_corners[(i + 2) * 2 + 1]) - (cell_corners[i * 2 + 1] - cell_corners[(i + 1) * 2 + 1]) 
+      * (cell_corners[(i + 1) * 2 + 0] - cell_corners[(i + 2) * 2 + 0]); 
+
     /* In the first iteration the direction of winding of the entire polygon is set. Better not be 0.*/
 
     if (i == 1){
       direction = turns_to;
     }
 
-    if (sign(direction) != sign(turns_to)){
-      if (direction != 0){
-	return 0;
+    if ( IS_NOT_EQUAL(sign(direction), sign(turns_to)) ){
+      if ( IS_NOT_EQUAL(direction, 0) ){
+	return false;
       }
     }
     else{
       direction = turns_to;
     }      
   }
-  return 1;
-}
-
-static double calculate_twice_the_polygon_area(double cell_corners[], int number_corners){
-
-  /* This algorithm works with non-convex and even self-intersecting polygons. It results in twice the area of the polygon. */
-  
-  double twice_the_polygon_area = 0;
-
-  for (int i = 0; i < number_corners - 1; i++){
-    
-    twice_the_polygon_area += (cell_corners[(i + 1) * 2 + 0] - cell_corners[i * 2 + 0]) * (cell_corners[(i + 1) * 2 + 1] - cell_corners[i * 2 + 1]);
-  }
-  return twice_the_polygon_area;
-}
-
-static int are_polygon_vertices_arranged_in_clockwise_order(double twice_the_cell_area){
-
-  /* A positive area indicates a clockwise arrangement of vertices, a negative area a counterclockwise arrangement. There should be an area to begin with. */
-  
-  double area_sign = sign(twice_the_cell_area);
-
-  if (area_sign > 0){
-    return 1;
-  }
-  if (area_sign < 0){
-    return 0;
-  }
-}
-
-
-
-double intlin(double x, double y1, double x1, double y2, double x2);
-
-static
-int pnpoly(int npol, double *xp, double *yp, double x, double y)
-{
-  int i, j, c = 0;
-
-  for (i = 0, j = npol-1; i < npol; j = i++) {
-    if ((((yp[i]<=y) && (y<yp[j])) ||
-	 ((yp[j]<=y) && (y<yp[i]))) &&
-	(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
-      
-      c = !c;
-  }
-  return c;
-}
 
-
-static
-double PolygonArea_old(int np, double *xp, double *yp)
-{
-  int i, j;
-  double area = 0;
-
-  for ( i = 0; i < np; i++ )
-    {
-      j = (i + 1) % np;
-      area += xp[i] * yp[j];
-      area -= yp[i] * xp[j];
-    }
-
-  area /= 2;
-  /* return(area < 0 ? -area : area); */
-  return (area);
+  return true;
 }
 
 
 static
-double PolygonArea(int np, double *xp, double *yp, double yc)
+double calculate_the_polygon_area(double cell_corners[], int number_corners)
 {
-  int i, j;
-  double area = 0.;
+  /* This algorithm is based on the calculation from Wolfram Mathworld Polygon Area. It results in the area of planar non-self-intersecting polygon. */
+  
+  double twice_the_polygon_area = 0;
 
-  /* Process area in Radians */
-   
-  for ( i = 0; i < np; i++ )
+  for (int i = 0; i < number_corners - 1; i++)
     {
-      j = (i + 1) % np;
-      area += DEG2RAD*xp[i] * DEG2RAD*yp[j];
-      area -= DEG2RAD*yp[i] * DEG2RAD*xp[j];
+      twice_the_polygon_area += (cell_corners[i * 2 + 0] * cell_corners[(i + 1) * 2 + 1]) - (cell_corners[(i + 1) * 2 + 0] * cell_corners[i * 2 + 1]); 
     }
-  area *= 0.5 * cos(DEG2RAD*yc);
-  return (area);
+  
+  return twice_the_polygon_area / 2;
 }
 
 static
-int ccw(double p0x, double p0y, double p1x, double p1y, double p2x, double p2y)
+bool are_polygon_vertices_arranged_in_clockwise_order(double cell_area)
 {
-  /*
-    This function says wether the point are orientated clockwise
-    +1 positive orientation
-    -1 negative orientation
-     0 points are on a line --> no orientation
-    
-    This is done by a comparision of the gradient of
-    dy1/dx1 = p1 - p0 vs.
-    dy2/dx2 = p2 - p0
-    To avoid singularities at dx1=0 OR dx2 = 0 we multiply with dx1*dx2
-  */
-  double dx1, dx2, dy1, dy2;
+  bool status = false;
 
-  dx1 = p1x - p0x; dy1 = p1y - p0y;
-  dx2 = p2x - p0x; dy2 = p2y - p0y;
-  if ( dx1*dy2 > dy1*dx2 ) return +1;
-  if ( dx1*dy2 < dy1*dx2 ) return -1;
-  if ( (dx1*dx2 < 0 ) || (dy1*dy2 < 0)) return -1;
-  if ( (dx1*dx1 + dy1*dy1) < (dx2*dx2 + dy2*dy2)) return +1;
+  /* A negative area indicates a clockwise arrangement of vertices, a positive area a counterclockwise arrangement. There should be an area to begin with. */
+  if ( cell_area < 0 ) status = true;
 
-  return 0;
+  return status;
 }
 
 static
-int intersect(double pix, double piy, double pjx, double pjy,
-              double pkx, double pky, double plx, double ply)
-{
-  /*This function returns if there is an intersection between the lines 
-    line1 between pi and pj and
-    line2 between pk and pl,
-    whereas pi = (pix, piy).
-      
-    This can done by means of ccw since the product of ccw(pi,pj,pk)*ccw(pi,pj,pl)
-    shows if pk and pl are on different or the same side(s) of the line1 (They must
-    have different signums to be on different sides).
-      
-    Consequently if and ONLY IF pk as well as pl are on different sides of line1
-    AND pi as well as pj are on different sides of line2 there HAS TO be an intersection.
-  */
-    
-  return ( ( ccw(pix, piy, pjx, pjy, pkx, pky) *
-	     ccw(pix, piy, pjx, pjy, plx, ply) <= 0 ) &&
-	   ( ccw(pkx, pky, plx, ply, pix, piy) *
-	     ccw(pkx, pky, plx, ply, pjx, pjy) <= 0 ) );
-}
+void verify_grid(int gridtype, int gridsize, int gridno, int ngrids, int ncorner, double *grid_center_lon, double *grid_center_lat, double *grid_corner_lon, double *grid_corner_lat){
 
-static
-int check_ncorner(int ncorner, const double *lon_bounds, const double *lat_bounds)
-{
-  int ncorner_new = ncorner;
-  int k;
+  /* 
+     First, this function performs the following test:
 
-  for ( k=ncorner-1; k>0; --k )
-    if ( IS_NOT_EQUAL(lon_bounds[k], lon_bounds[k-1]) ||
-	 IS_NOT_EQUAL(lat_bounds[k], lat_bounds[k-1]) ) break;
+     1) it tests whether there are duplicate cells in the given grid by comparing their center points
 
-  if ( k < ncorner-1 ) ncorner_new = k+1;
+     Additionally, on each cell of a given grid:
 
-  return ncorner_new;
-}
+     2) it tests whether all cells are convex and all cell bounds have the same orientation, i.e. the corners of the cell are in clockwise or counterclockwise order
+     3) it tests whether the center point is within the bounds of the cell
 
-static
-void verify_grid(int gridsize, int ncorner,
-		double *grid_center_lon, double *grid_center_lat,
-		double *grid_corner_lon, double *grid_corner_lat)
-{
-  int i0, i, j, k, l;
-  int l0;
-  int nout;
-  int isinside, convex, alone, isnegative;
-  const int mnv = ncorner+1;
-  int cuts[mnv][mnv];  
-  int *alone_cell;          
-  int check_corners;
-  double lon, lat = 0;
-  double lon_bounds[mnv], lat_bounds[mnv];
-  double area, sumarea;
-
-  alone_cell = (int*) Malloc(gridsize*ncorner*sizeof(int));
-
-  check_corners = 0; /* don't execute corner checking (last loop) */
-  nout = 0;
-  sumarea = 0;
-  /*
-  for ( i = 0; i < gridsize; ++i )
-    {
-      lon = grid_center_lon[i];
-      lat = grid_center_lat[i];
-      for ( k = 0; k < ncorner; ++k )
-        {
-          lon_bounds[k] = grid_corner_lon[i*ncorner+k];
-          lat_bounds[k] = grid_corner_lat[i*ncorner+k];
-          if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
-          if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
-        }      
-      lon_bounds[ncorner] = lon_bounds[0];
-      lat_bounds[ncorner] = lat_bounds[0];
-      fprintf(stdout, " %6i %6i %9.4f %9.4f :",  nout, i+1, lon, lat);
-      for ( k = 0; k < ncorner; k++ )
-	fprintf(stdout, " %9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
-      fprintf(stdout, "\n");
-    }
+     The results of the tests are printed on stdout.
   */
+  
+  double center_point_in_Euclidean_space[3];
+  double cell_corners_in_Euclidean_space_open_cell[ncorner * 3];
+  
+  double corner_coordinates[3];
+  double second_corner_coordinates[3];
+  double third_corner_coordinates[3];
+  double surface_normal_of_the_cell[3];
+  double center_point_plane_projection[2];
+
+  int cell_no = 0;
+  int corner_no = 0;
+  int actual_number_of_corners = 0;
+  int no_of_cells_with_duplicates = 0;
+  int no_convex_cells = 0;
+  int no_clockwise_cells = 0;
+  int no_counterclockwise_cells = 0;
+  int winding_number = 0;
+  int no_of_cells_with_center_points_out_of_bounds = 0;
+  int coordinate_to_ignore = 0;
+  int subarray_start = 0;
+  int subarray_end = 0;
+  int no_unique_center_points = 1;
+
+  double abs_x = 0; 
+  double abs_y = 0; 
+  double abs_z = 0;
+  double polygon_area = 0;
+  
+  double * p_surface_normal_of_the_cell;
+  p_surface_normal_of_the_cell = &surface_normal_of_the_cell[0];
 
-  /* Check if center is inside bounds of cell */
-  for ( i = 0; i < gridsize; ++i )
-    {
-      lon = grid_center_lon[i];
-      lat = grid_center_lat[i];
-
-      for ( k = 0; k < ncorner; ++k )
-        {
-          lon_bounds[k] = grid_corner_lon[i*ncorner+k];
-          lat_bounds[k] = grid_corner_lat[i*ncorner+k];
-          if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
-          if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
-        }      
-      lon_bounds[ncorner] = lon_bounds[0];
-      lat_bounds[ncorner] = lat_bounds[0];
-      
-      isinside = pnpoly(ncorner+1, lon_bounds, lat_bounds, lon, lat);
+  int no_cells_with_a_specific_no_of_corners[ncorner];
 
-      if ( !isinside ) nout++;
-      if ( !isinside && cdoVerbose )
-        {
-          if ( nout == 1 )
-            {
-              fprintf(stdout,"\n CENTER IS OUT OF BOUNDS");
-              fprintf(stdout,"\n                                               :");
-              for ( k = 0; k < ncorner; k++ )
-                fprintf(stdout, "          Corner %2i : ", k+1);
-              fprintf(stdout,"\n Number  Index center_lon center_lat area*10^6 :");
-              for ( k = 0; k < ncorner; k++ )
-                fprintf(stdout, "   lon_%2.2i    lat_%2.2i : ", k+1, k+1);
-              fprintf(stdout, "\n");
-            }
-          area = PolygonArea(ncorner+1, lon_bounds, lat_bounds,lat);
-          fprintf(stdout, " %6i %6i  %9.4f  %9.4f %9.5f :", 
-		  nout, i+1, lon, lat, area*pow(10,6));
+  for ( int i = 0; i < ncorner; i++ )
+    no_cells_with_a_specific_no_of_corners[i] = 0;
 
-	  int ncorner_new = check_ncorner(ncorner, lon_bounds, lat_bounds);
+  if ( ngrids == 1 )
+    cdoPrintBlue("Grid consists of %d cells (type: %s), of which", gridsize, gridNamePtr(gridtype));
+  else
+    cdoPrintBlue("Grid no %u (of %u) consists of %d cells (type: %s), of which", gridno + 1, ngrids, gridsize, gridNamePtr(gridtype));
+  //cdoPrint("");
 
-          for ( k = 0; k < ncorner_new; k++ )
-	    fprintf(stdout, "%9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
-           for ( k = ncorner_new; k < ncorner; k++ )
-	     fprintf(stdout, "     ----      ---- : ");
-          fprintf(stdout, "\n");
-        }
-    }
+  /* For performing the first test, an array of all center point coordinates is built. */
 
-  if ( nout )
-    cdoWarning("%d of %d points out of bounds!", nout, gridsize);
+  double * center_point_array = (double *)Malloc(gridsize * 2 * sizeof(double));
   
-  /* check that all cell bounds have the same orientation */
+  for(cell_no = 0; cell_no < gridsize; cell_no++){
+    center_point_array[cell_no * 2 + 0] = grid_center_lon[cell_no];
+    center_point_array[cell_no * 2 + 1] = grid_center_lat[cell_no];
+  }
+
   
-  nout = 0;
-  for ( i = 0; i < gridsize; ++i )
-    {
-      lon = grid_center_lon[i];
-      lat = grid_center_lat[i];
-      
-      for ( k = 0; k < ncorner; ++k )
-	{
-          lon_bounds[k] = grid_corner_lon[i*ncorner+k];
-          lat_bounds[k] = grid_corner_lat[i*ncorner+k];
-          if ( (grid_center_lon[i] - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
-          if ( (lon_bounds[k] - grid_center_lon[i]) > 270 ) lon_bounds[k] -= 360;
-	}
-      lon_bounds[ncorner] = lon_bounds[0];
-      lat_bounds[ncorner] = lat_bounds[0];
-      
-      area = PolygonArea(ncorner+1, lon_bounds, lat_bounds, lat);
-      
-      isnegative = area < 0 ? 1 : 0;
-      sumarea += area < 0 ? -area : area;
-      
-      if ( isnegative ) nout++;
-      
-      if ( isnegative && cdoVerbose )
-        {
-          if ( nout == 1 )
-            {
-              fprintf(stdout,"\n                                     :");
-              for ( k = 0; k < ncorner; k++ )
-                fprintf(stdout, "          Corner %2i : ", k+1);
-              fprintf(stdout,"\n Number  Index center_lon center_lat :");
-              for ( k = 0; k < ncorner; k++ )
-                fprintf(stdout, "   lon_%2.2i    lat_%2.2i : ", k+1, k+1);
-              fprintf(stdout, "\n");
-            }
-          fprintf(stdout, " %6i %6i  %9.4f  %9.4f :", nout, i+1, lon, lat);
 
-	  int ncorner_new = check_ncorner(ncorner, lon_bounds, lat_bounds);
+  /* The cell center points are sorted by their first coordinate (lon) with quicksort. */
 
-          for ( k = 0; k < ncorner_new; k++ )
-	    fprintf(stdout, "%9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
-           for ( k = ncorner_new; k < ncorner; k++ )
-	     fprintf(stdout, "     ----      ---- : ");
+  quick_sort_by_lon(center_point_array, gridsize * 2);
+  
+  /* Now the lat coordinates in subarrays that reflect equal lon coordinates are sorted with quicksort. */
 
-          fprintf(stdout, "\n");
-        }
-    }
+  for(cell_no = 0; cell_no < gridsize - 1; cell_no++){
 
-  if ( nout )
-    cdoWarning("%d of %d grid cells have wrong orientation!", nout, gridsize);
+    if(cell_no == gridsize - 2){    
+      subarray_end = gridsize * 2 - 2;      
+      quick_sort_of_subarray_by_lat(center_point_array, subarray_start, subarray_end);
+    }
+            
+    if(fabs(center_point_array[cell_no * 2 + 0] - center_point_array[(cell_no + 1)  * 2  + 0]) > 0.0001){     
+      subarray_end = cell_no * 2;    
+      if((subarray_end - subarray_start) > 1){	
+	quick_sort_of_subarray_by_lat(center_point_array, subarray_start, subarray_end);
+      }     
+      subarray_start = subarray_end + 2;  
+    }        
+  }
 
-  if ( cdoVerbose ) 
-    fprintf(stdout, "area-error: %9.5f%%\n", 100.*(sumarea - 4.*M_PI)/4.*M_PI );
+  /* Now checking for the number of unique center point coordinates. */
 
-  if ( fabs(100.*(sumarea - 4.*M_PI)/4.*M_PI) > 0.1)
-    cdoWarning("area-error: %9.5f%%", 100.*(sumarea - 4.*M_PI)/4.*M_PI );
+  for(cell_no = 0; cell_no < gridsize - 1; cell_no++){
+    if(fabs(center_point_array[cell_no * 2 + 0] - center_point_array[(cell_no + 1) * 2 + 0]) < 0.0001){
+      if(fabs(center_point_array[cell_no * 2 + 1] - center_point_array[(cell_no + 1) * 2 + 1]) < 0.0001){
+	continue;
+      } else {
+	no_unique_center_points += 1;
+      }
+    } else {
+      	no_unique_center_points += 1;
+    }
+  }
   
-  /* check that all cells are convex */
+  Free(center_point_array);
+
+  /* 
+     Latitude and longitude are spherical coordinates on a unit circle. Each such coordinate tuple is transformed into a triple of Cartesian coordinates in Euclidean space. 
+     This is first done for the presumed center point of the cell and then for all the corners of the cell. LLtoXYZ is defined in clipping/geometry.h 
+  */
   
-  nout = 0;
-  for ( i0 = 0; i0 < gridsize; i0++ )
-    {
-      lon = grid_center_lon[i0];
-      lat = grid_center_lat[i0];
-
-      for ( k = 0; k < ncorner; k++ )
-	{
-	  lon_bounds[k] = grid_corner_lon[i0*ncorner+k];
-	  lat_bounds[k] = grid_corner_lat[i0*ncorner+k];
-	  /* Find cells that cover left and right border of the grid and adjust
-	     coordinates --> they become closed polygons on theta-phi plane! */
-	  if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360; 
-	  if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
-	}
-      
-      /* Reset found cuts for the current cell before starting the search */
-      for ( i = 0; i < ncorner; i++ )
-	for ( j = 0; j < ncorner; j++ )
-	  cuts[i][j] = 0;
-      
-      /* Loops cover all combinations between inner lines of the Polygon
-	 Check whether each inner line is cut by an other (inner) one at least once. 
-	 - Only if there is a cut every inner line the Polygon is convex
-	 - We assume: Points are in either cyclic or anticyclic order
-      */
-      for ( i = 0; i < ncorner-1; i++ )
-	{
-          /* j = i+2 excludes lines from one corner to an other (j=i+1) and
-	     from one point to itself (j=i)*/
-          for ( j = i+2 ; j < ncorner; j++ )
-	    {
-              /* Exclude the line between the last and first corner */
-              if ( i == 0 && j == ncorner-1 ) continue;
-
-	      /* k = i+1: if starting point is in common lines to different corners
-		 do not intersect */
-              for ( k = i+1; k < ncorner - 1; k++ )
-		{                  
-                  if ( i == k ) l0 = j+1;
-                  else          l0 = k+2;
-
-                  for ( l = l0; l < ncorner; l++ )
-		    {
-                      if ( cuts[k][l] && cuts[i][j] ) continue;
-		      /* Exlude the line between the last and first corner 
-			 Exlude the line itself (l!=i, k!=j)
-			 Check if line ij and kl intersect each other.
-			 If so increment respective counters for intersections. 
-			 It is not relevant by which line a line is intersected - 
-			 it is only relevant if they is itersected! */
-                      if ( ! ( k==0 && l == ncorner-1 ) && ( l != j ) && ( k != j )  )
-			{
-                          if ( intersect(lon_bounds[i], lat_bounds[i], lon_bounds[j], lat_bounds[j],
-                                         lon_bounds[k], lat_bounds[k], lon_bounds[l], lat_bounds[l]) )
-			    {
-			      cuts[i][j]++; cuts[k][l]++; cuts[j][i]++; cuts[l][k]++;
-			    }
-			}
-		    }
-		}                  
-	    }
-	}
 
-      convex = 1;
-      /* The following loop covers all inner lines of the Polygon 
-	 (The assumption applies that the points are in cyclic order) */
-      for ( i = 0; i < ncorner-1; i++ )
-	for ( j = i+2; j < ncorner; j++)
-	  {
-	    if ( i == 0 && j == ncorner-1 ) continue;	   
-	    if ( ! cuts[i][j] ) convex = 0;
-	  }
-      if ( !convex ) nout++;        
-      if ( cdoVerbose && ( !convex ) )
-	{
-          if ( nout == 1 )
-	    {
-              fprintf(stdout,"\n NO CONVEX POLYGON");
-              fprintf(stdout,"\n                                       :");
-              for ( k = 0; k < ncorner; k++ )
-		fprintf(stdout, "            Corner %2i : ", k);
-              fprintf(stdout,"\n Number  Index  center_lon  center_lat :");
-              for ( k = 0; k < ncorner; k++ )
-		fprintf(stdout, "    lon_%2.2i     lat_%2.2i : ", k, k);
-              fprintf(stdout, "\n");
-	    }
-          
-          fprintf(stdout, " %6i %6i   %9.4f   %9.4f :", nout, i0+1, lon, lat);
-          for ( k = 0; k < ncorner; k++ )
-	    fprintf(stdout, "  %9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
-          fprintf(stdout, "\n");         
-	}     
-    }
+  for ( cell_no = 0; cell_no < gridsize; cell_no++ )
+    {    
+      /* Conversion of center point spherical coordinates to Cartesian coordinates. */
 
-  if ( nout )
-    cdoWarning("%d of %d cells are not Convex!", nout, gridsize);
+      LLtoXYZ_deg(grid_center_lon[cell_no], grid_center_lat[cell_no], center_point_in_Euclidean_space);
+      
+      for (corner_no = 0; corner_no < ncorner; corner_no++)
+	{	  
+	  /* Conversion of corner spherical coordinates to Cartesian coordinates. */
 
-  if ( check_corners )
-    {
+	  LLtoXYZ_deg(grid_corner_lon[cell_no * ncorner + corner_no], grid_corner_lat[cell_no * ncorner + corner_no], corner_coordinates);
+	  
+	  /* The components of the result vector are appended to the list of cell corner coordinates. */
+	  
+	  cell_corners_in_Euclidean_space_open_cell[corner_no * 3 + 0] = corner_coordinates[0];	  
+	  cell_corners_in_Euclidean_space_open_cell[corner_no * 3 + 1] = corner_coordinates[1];	  
+	  cell_corners_in_Euclidean_space_open_cell[corner_no * 3 + 2] = corner_coordinates[2];	  
+	}
+      
       /* 
-	 Check if there is a corner at the same point of 
-	 an other cell foreach corner of each cell 
+	 Not all cells have the same number of corners. The array, however, has ncorner * 3  values for each cell, where ncorner is the maximum number of corners. Unused values have been filled with the values of the final cell.
+	 The following identifies the surplus corners and gives the correct length of the cell.
       */
-      nout = 0;
-      for ( i = 0; i < gridsize*ncorner; i++ )
-	alone_cell[i] = 1;
       
-      for ( i = 0; i < gridsize*ncorner; i++ )
-	{
-	  if ( ! alone_cell[i] ) continue;
-	  alone = 1;
-	  lon = grid_corner_lon[i];
-	  lat = grid_corner_lat[i];			
-	  for ( j = 0; j < gridsize*ncorner; j++ )
-	    if ( j != i && 
-		 IS_EQUAL(grid_corner_lat[j], lat) && 
-		 IS_EQUAL(grid_corner_lon[j], lon) )
-	      { alone = 0; alone_cell[i] = alone_cell[j] = 1; break; }
-	  if ( alone )
-	    {
-	      if      ( lon >= 180. ) lon -= 360.;
-	      else if ( lon  < 180. ) lon += 360.;
-	      for ( j = i+1; j < gridsize*ncorner; j++ )
-		if (j != i  && 
-		    IS_EQUAL(grid_corner_lat[j], lat) && 
-		    IS_EQUAL(grid_corner_lon[j], lon) )
-		  { alone = 0; alone_cell[i] = alone_cell[j] = 0; break; }
-	    }
-	  if ( alone )
-	    { 
-	      nout++;
-	      if ( cdoVerbose )
-		{
-		  if ( nout == 1 )
-		    {
-		      fprintf(stdout,"\n VERTEX ALONE ON GRID\n");
-		      fprintf(stdout," number cell-Index  Vert-Index :        lon        lat\n");
-		    }							
-		  fprintf(stdout, " %6i     %6i      %6i : %10.4f %10.4f\n", 
-			  nout, i/ncorner, i, grid_corner_lon[i], grid_corner_lat[i]);
-		}					
-	    }
+      actual_number_of_corners = ncorner;
+
+      double *cell_corners = cell_corners_in_Euclidean_space_open_cell;
+      for (corner_no = ncorner - 1; corner_no > 0; corner_no--){
+	if ( IS_EQUAL(cell_corners[corner_no * 3 + 0], cell_corners[(corner_no - 1) * 3 + 0]) &&
+             IS_EQUAL(cell_corners[corner_no * 3 + 1], cell_corners[(corner_no - 1) * 3 + 1]) &&
+             IS_EQUAL(cell_corners[corner_no * 3 + 2], cell_corners[(corner_no - 1) * 3 + 2]) ){
+          actual_number_of_corners = actual_number_of_corners - 1;
+        } else {
+	  break;
+	}	
+      }                  
+
+      no_cells_with_a_specific_no_of_corners[actual_number_of_corners - 1] += 1;
+      
+      /* If there are less than three corners in the cell, it is unusable and considered degenerate. No area can be computed. */
+      
+      if (actual_number_of_corners < 3){
+	if (cdoVerbose){
+	  fprintf(stdout,"Less than three vertices found in cell no %u. This cell is considered degenerate and will be omitted from further computation!\n", cell_no + 1);
 	}
+	continue;
+      }
+      
+      /* Checks if there are any duplicate vertices in the list of corners. Note that the last (additional) corner has not been set yet. */
 
-      if ( nout )
-	cdoWarning("%d of %d corners are lonely on the grid!", nout, gridsize*ncorner);
-    }
-
-  Free(alone_cell);
-}
-
-
-void verify_grid_old(int gridsize, int ncorner,
-		double *grid_center_lon, double *grid_center_lat,
-		double *grid_corner_lon, double *grid_corner_lat)
-{
-  int i, k;
-  int nout;
-  int isinside;
-  int isnegative;
-  double area;
-  double lon, lat;
-  double lon_bounds[ncorner], lat_bounds[ncorner];
-
-  /* check that all centers are inside the bounds */
-
-  nout = 0;
-  for ( i = 0; i < gridsize; ++i )
-    {
-      lon = grid_center_lon[i];
-      lat = grid_center_lat[i];
+      int marked_duplicate_indices[actual_number_of_corners];
 
-      for ( k = 0; k < ncorner; ++k )
-	{
-	  lon_bounds[k] = grid_corner_lon[i*ncorner+k];
-	  lat_bounds[k] = grid_corner_lat[i*ncorner+k];
-	}
+      for(int i = 0; i < actual_number_of_corners; i++){
+	marked_duplicate_indices[i] = 0;
+      }
 
-      for ( k = 0; k < ncorner; ++k )
-	{
-	  if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
-	  if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
+      int no_duplicates = 0;
+      
+      for (int i = 0; i < actual_number_of_corners * 3; i = i + 3){
+	for (int j = i + 3; j < actual_number_of_corners * 3; j = j + 3 ){
+	  if (fabs(cell_corners_in_Euclidean_space_open_cell[i + 0] - cell_corners_in_Euclidean_space_open_cell[j]) < 0.000001){
+	    if (fabs(cell_corners_in_Euclidean_space_open_cell[i + 1] - cell_corners_in_Euclidean_space_open_cell[j + 1]) < 0.000001){
+	      if (fabs(cell_corners_in_Euclidean_space_open_cell[i + 2] - cell_corners_in_Euclidean_space_open_cell[j + 2]) < 0.000001){
+		if (cdoVerbose){
+		  fprintf(stdout,"The duplicate vertex %f, %f, %f was found in cell no %u.\n", cell_corners_in_Euclidean_space_open_cell[j],  cell_corners_in_Euclidean_space_open_cell[j + 1],  cell_corners_in_Euclidean_space_open_cell[j + 2], cell_no + 1);
+		}
+		no_duplicates += 1;
+		marked_duplicate_indices[j / 3] = 1;
+	      }
+	    }
+	  }
 	}
+      }
 
-      lon_bounds[ncorner] = lon_bounds[0];
-      lat_bounds[ncorner] = lat_bounds[0];
-
-      isinside = pnpoly(ncorner+1, lon_bounds, lat_bounds, lon, lat);
-
-      if ( !isinside ) nout++;
-
-      if ( !isinside && cdoVerbose )
-	printf("center: %d %d %g %g %g %g %g %g %g %g %g %g\n", nout, i, lon, lat, lon_bounds[0], lat_bounds[0],
-	       lon_bounds[1], lat_bounds[1], lon_bounds[2], lat_bounds[2], lon_bounds[3], lat_bounds[3]);
-    }
-
-  if ( nout > 0 )
-    cdoWarning("%d of %d points out of bounds!", nout, gridsize);
-
-
-  /* check that all cell bounds have the same orientation */
 
-  nout = 0;
-  for ( i = 0; i < gridsize; ++i )
-    {
-      lon = grid_center_lon[i];
-      lat = grid_center_lat[i];
+      /* Writes the unique corner vertices in a new array. */
 
-      for ( k = 0; k < ncorner; ++k )
-	{
-	  lon_bounds[k] = grid_corner_lon[i*ncorner+k];
-	  lat_bounds[k] = grid_corner_lat[i*ncorner+k];
+      double cell_corners_in_Euclidean_space_without_duplicates[(actual_number_of_corners - no_duplicates) * 3];
+      
+      int unique_corner_number = 0;
+      
+      for(int corner_number = 0; corner_number < actual_number_of_corners; corner_number++){
+	if(marked_duplicate_indices[corner_number] == 0){
+	  cell_corners_in_Euclidean_space_without_duplicates[unique_corner_number * 3 + 0] = cell_corners_in_Euclidean_space_open_cell[corner_number * 3 + 0];
+	  cell_corners_in_Euclidean_space_without_duplicates[unique_corner_number * 3 + 1] = cell_corners_in_Euclidean_space_open_cell[corner_number * 3 + 1];
+	  cell_corners_in_Euclidean_space_without_duplicates[unique_corner_number * 3 + 2] = cell_corners_in_Euclidean_space_open_cell[corner_number * 3 + 2];
+	  unique_corner_number += 1;
 	}
+      }
+      
+      actual_number_of_corners = actual_number_of_corners - no_duplicates;
 
-      for ( k = 0; k < ncorner; ++k )
-	{
-	  if ( (grid_center_lon[i] - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
-	  if ( (lon_bounds[k] - grid_center_lon[i]) > 270 ) lon_bounds[k] -= 360;
+      /* If there are less than three corners in the cell left after removing duplicates, it is unusable and considered degenerate. No area can be computed. */
+      
+      if (actual_number_of_corners < 3){
+	if (cdoVerbose){
+	  fprintf(stdout,"Less than three vertices found in cell no %u. This cell is considered degenerate and will be omitted from further computation!\n", cell_no + 1);
 	}
+	continue;
+      }
+      
+      if (no_duplicates != 0){
+	no_of_cells_with_duplicates += 1;
+      }
 
-      lon_bounds[ncorner] = lon_bounds[0];
-      lat_bounds[ncorner] = lat_bounds[0];
-
-      area = PolygonArea_old(ncorner+1, lon_bounds, lat_bounds);
-
-      if ( area < 0 ) isnegative = 1;
-      else            isnegative = 0;
-
-      if ( isnegative ) nout++;
-
-
-      if ( isnegative && cdoVerbose )
-	printf("bounds: %d %d %g %g %g %g %g %g %g %g %g %g\n", nout, i, lon, lat, lon_bounds[0], lat_bounds[0],
-	       lon_bounds[1], lat_bounds[1], lon_bounds[2], lat_bounds[2], lon_bounds[3], lat_bounds[3]);
-    }
-
-  if ( nout > 0 )
-    cdoWarning("%d of %d grid cells have wrong orientation!", nout, gridsize);
-}
-
-
-static void verify_grid_test(int gridsize, int ncorner, double *grid_center_lon, double *grid_center_lat, double *grid_corner_lon, double *grid_corner_lat){
-
-
-
-  /* 
-     This function performs three tests on each cell of a given grid:
-
-     1) it tests whether all cell bounds have the same orientation, i.e. the corners of the cell are in clockwise or counterclockwise order
-     2) it tests whether the cell is convex
-     3) it tests whether the center point is within the bounds of the cell
-
-     It performs these tests after longitude and latitude on the unit circle have been converted first to Cartesian coordinates in Euclidean space and subsequently to two dimensional coordinates on the plane each cell occupies.  
-  */
-  
-  double center_point_in_Euclidean_space[3];
-
-  /* We are assuming a maximum number of corners of 9. The 10th corner is for closing the cell. */
-
-  double cell_corners_in_Euclidean_space[30];
-  double cell_corner_coordinates[3];
-  double center_point_on_cell_plane[2];
-  double cell_corners_on_cell_plane[20];
-
-  int cell_no;
-  int corner_no;
-
-  int no_of_cells_with_vertices_arranged_in_clockwise_order = 0;
-  int no_of_cells_with_vertices_arranged_in_counterclockwise_order = 0;
-  int no_of_convex_cells = 0;
-  int no_of_degenerate_cells = 0;
-  int no_of_cells_with_center_points_within_their_bounds = 0;
-
-  for (cell_no = 0; cell_no < gridsize; ++cell_no)
-    {
-       printf("Cell Number %d:\n\n", cell_no+1);
-       printf("Euclidean coordinates are:\n\n");
-       
-       /* 
-	  Latitude and longitude are spherical coordinates on a unit circle. Each such coordinate tuple is transformed into a triple of Cartesian coordinates in Euclidean space.
-	  This is first done for the presumed center point of the cell and then for all the corners of the cell. LLtoXYZ is defined in clipping/geometry.h 
-       */
-
-      LLtoXYZ(grid_center_lon[cell_no], grid_center_lat[cell_no], center_point_in_Euclidean_space);
-
-      for (corner_no = 0; corner_no < ncorner; ++corner_no)
-	{
-	  LLtoXYZ(grid_corner_lon[cell_no * ncorner + corner_no], grid_corner_lat[cell_no * ncorner + corner_no], cell_corner_coordinates);
+      /* We are creating a closed polygon/cell by setting the additional last corner to be the same as the first one. */
 
-	  /* The components of the result vector are appended to the list of cell corner coordinates. */
+      double cell_corners_in_Euclidean_space[(actual_number_of_corners + 1) * 3];
 
-	  for (int vector_component = 0; vector_component < 3; ++vector_component){	    
-	    cell_corners_in_Euclidean_space[(corner_no * 3) + vector_component] = cell_corner_coordinates[vector_component];	  
-	  }
-	  printf("(%f, %f, %f) ", cell_corners_in_Euclidean_space[(corner_no * 3) + 0], cell_corners_in_Euclidean_space[(corner_no * 3) + 1], cell_corners_in_Euclidean_space[(corner_no * 3) + 2]);
-	}
+      for (corner_no = 0; corner_no < actual_number_of_corners; corner_no++){
+	cell_corners_in_Euclidean_space[corner_no * 3 + 0] = cell_corners_in_Euclidean_space_without_duplicates[corner_no * 3 + 0];
+	cell_corners_in_Euclidean_space[corner_no * 3 + 1] = cell_corners_in_Euclidean_space_without_duplicates[corner_no * 3 + 1];
+	cell_corners_in_Euclidean_space[corner_no * 3 + 2] = cell_corners_in_Euclidean_space_without_duplicates[corner_no * 3 + 2];
+      }
 
-      /* We are creating a closed polygon/cell by setting the last corner to be the same as the first one. */
+      cell_corners_in_Euclidean_space[actual_number_of_corners * 3 + 0] = cell_corners_in_Euclidean_space[0];
+      cell_corners_in_Euclidean_space[actual_number_of_corners * 3 + 1] = cell_corners_in_Euclidean_space[1];
+      cell_corners_in_Euclidean_space[actual_number_of_corners * 3 + 2] = cell_corners_in_Euclidean_space[2];
 
-      for (int vector_component = 0; vector_component < 3; ++vector_component){
-	cell_corners_in_Euclidean_space[(ncorner * 3) + vector_component] = cell_corners_in_Euclidean_space[vector_component];
-      }
+      /* Takes the first three corners/vertices of the cell and calculates the unit normal via determinants. */
       
-      printf("\n\n");
-           
-
-      /*
-	Each cell corresponds to a two-dimensional polygon now in unknown orientation in three-dimensional space. Each cell and its center point are coplanar. THIS IS A GIVEN.
-	In order to solve the two-dimensional point-in-polygon problem for each cell, the three-dimensional coordinates of the polygon and its center point are projected onto the two-dimensional plane they form.
-        
-	This is done in the following steps:
+      corner_coordinates[0] = cell_corners_in_Euclidean_space[0];
+      corner_coordinates[1] = cell_corners_in_Euclidean_space[1];
+      corner_coordinates[2] = cell_corners_in_Euclidean_space[2];
 
-	1) Compute two vectors that lie on the cell plane. The first three corners of the cell are used to do this. THIS MEANS THAT AT LEAST THREE CORNERS MUST BE GIVEN.
-	   Then compute the normal of the cell plane the two vectors are on. The normal is the new z-axis.
-	2) Compute the new y-axis by computing the cross product of the new z-axis and the old x-axis.
-	3) Compute the new x-axis by computing the cross product of the new z-axis and the new y-axis.
-	4) Project every corner point onto the new x- and y-axes by using the dot product.
+      second_corner_coordinates[0] = cell_corners_in_Euclidean_space[3 + 0];
+      second_corner_coordinates[1] = cell_corners_in_Euclidean_space[3 + 1];
+      second_corner_coordinates[2] = cell_corners_in_Euclidean_space[3 + 2];
 
-	The result is a xy tuple for each corner and the presumend center point which is a projection onto the plane the xyz corner points form.
-      */
-      
-      struct axis new_z_axis = compute_the_new_z_axis(cell_corners_in_Euclidean_space);      
-      struct axis new_y_axis = compute_the_new_y_axis(new_z_axis);      
-      struct axis new_x_axis = compute_the_new_x_axis(new_z_axis, new_y_axis);
+      third_corner_coordinates[0] = cell_corners_in_Euclidean_space[6 + 0];
+      third_corner_coordinates[1] = cell_corners_in_Euclidean_space[6 + 1];
+      third_corner_coordinates[2] = cell_corners_in_Euclidean_space[6 + 2];
       
-      project_Euclidean_corner_coordinates_onto_the_cell_plane(new_x_axis, new_y_axis, &cell_corners_in_Euclidean_space, &cell_corners_on_cell_plane, ncorner);
-      project_Euclidean_center_coordinates_onto_the_cell_plane(new_x_axis, new_y_axis, &center_point_in_Euclidean_space, &center_point_on_cell_plane);
-
-      /* Checking whether the cell has a size greater zero. */
+      find_unit_normal(corner_coordinates, second_corner_coordinates, third_corner_coordinates, p_surface_normal_of_the_cell);
 
-      double twice_the_cell_area = calculate_twice_the_polygon_area(cell_corners_on_cell_plane, ncorner);
+      /* The surface normal is used to choose the coordinate to ignore. */
 
-      if (twice_the_cell_area == 0){
-	printf("This cell is degenerate. Its area equals zero.\n\n");
-	no_of_degenerate_cells += 1;	
-	continue;	 
-      }
+      abs_x = fabs(surface_normal_of_the_cell[0]);
+      abs_y = fabs(surface_normal_of_the_cell[1]);
+      abs_z = fabs(surface_normal_of_the_cell[2]);
 
-      /* Checking whether the cell corners/polygon vertices are arranged in a clockwise or counterclockwise order. This is done by looking at the sign of the cell area. */
+      coordinate_to_ignore = 3;
 
-      if (are_polygon_vertices_arranged_in_clockwise_order(twice_the_cell_area) == 1){
-	printf("The cell's corners are arranged in clockwise order.\n\n");
-	no_of_cells_with_vertices_arranged_in_clockwise_order += 1;
+      if (abs_x > abs_y){
+	if (abs_x > abs_z){
+	  coordinate_to_ignore = 1;
+	}
       } else {
-	printf("The cell's corners are arranged in counterclockwise order.\n\n");
-	no_of_cells_with_vertices_arranged_in_counterclockwise_order += 1;
+	if (abs_y > abs_z){
+	  coordinate_to_ignore = 2;
+	}
       }
-  
-      /* Convexity of the cell is tested. */
-
-      printf("Checking if the cell is convex ... ");
+     
+      /* The remaining two-dimensional coordinates are extracted into one array for all the cell's corners and into one array for the center point. */
 
-      if (is_simple_polygon_convex(cell_corners_on_cell_plane, ncorner) == 1){
-	printf("cell is convex!\n\n");
-	no_of_convex_cells += 1;
-      } else {
-	printf("cell is not convex!\n\n");
-	no_of_degenerate_cells += 1;
-      }
-    
-      /* The winding numbers algorithm is used to test whether the presumed center point is within the bounds of the cell. */
-        
-      int winding_number = winding_numbers_algorithm_without_printfs(cell_corners_on_cell_plane, ncorner, center_point_on_cell_plane);
+      double cell_corners_plane_projection[(actual_number_of_corners +1) * 2];
+      
+      /* The following projection on the plane that two coordinate axes lie on changes the arrangement of the polygon vertices if the coordinate to be ignored along the third axis is smaller than 0.
+	 In this case, the result of the computation of the orientation of vertices needs to be inverted. Clockwise becomes counterclockwise and vice versa. */
 
-      if (winding_number == 0){
-	printf("The presumed center point lies OUTSIDE the bounds of the cell.\n\n\n\n");
-      } else {
-	printf("The presumed center point lies INSIDE the bounds of the cell.\n\n\n\n");
-	no_of_cells_with_center_points_within_their_bounds += 1;
+      bool invert_result = false;
+      if ( cell_corners_in_Euclidean_space[coordinate_to_ignore - 1] < 0 )
+	invert_result = true;
+      
+      switch(coordinate_to_ignore){
+      case 1:
+	for(corner_no = 0; corner_no <= actual_number_of_corners; corner_no++){
+	  cell_corners_plane_projection[corner_no * 2 + 0] = cell_corners_in_Euclidean_space[corner_no * 3 + 1];
+	  cell_corners_plane_projection[corner_no * 2 + 1] = cell_corners_in_Euclidean_space[corner_no * 3 + 2];
+	}
+	center_point_plane_projection[0] = center_point_in_Euclidean_space[1];
+	center_point_plane_projection[1] = center_point_in_Euclidean_space[2];		
+	break;
+      case 2:
+	for(int corner_no = 0; corner_no <= actual_number_of_corners; corner_no++){
+	  cell_corners_plane_projection[corner_no * 2 + 0] = cell_corners_in_Euclidean_space[corner_no * 3 + 2];
+	  cell_corners_plane_projection[corner_no * 2 + 1] = cell_corners_in_Euclidean_space[corner_no * 3 + 0];
+	}
+	center_point_plane_projection[0] = center_point_in_Euclidean_space[2];
+	center_point_plane_projection[1] = center_point_in_Euclidean_space[0];	
+	break;
+      case 3:
+	for(int corner_no = 0; corner_no <= actual_number_of_corners; corner_no++){
+	  cell_corners_plane_projection[corner_no * 2 + 0] = cell_corners_in_Euclidean_space[corner_no * 3 + 0];
+	  cell_corners_plane_projection[corner_no * 2 + 1] = cell_corners_in_Euclidean_space[corner_no * 3 + 1];
+	}
+	center_point_plane_projection[0] = center_point_in_Euclidean_space[0];
+	center_point_plane_projection[1] = center_point_in_Euclidean_space[1];	
+	break;
       }
-    }
-  
-  printf("There are %u cells in all.\n\n", gridsize );
-  printf("Number of cells with clockwise ordering of vertices: %u\n", no_of_cells_with_vertices_arranged_in_clockwise_order);
-  printf("Number of cells with counterclockwise ordering of vertices: %u\n", no_of_cells_with_vertices_arranged_in_counterclockwise_order);
-  printf("Number of convex cells: %u\n", no_of_convex_cells);
-  printf("Number of nonsimple or degenerate cells: %u\n", no_of_degenerate_cells);
-  printf("Number of cells with presumed center points within their bounds: %u\n", no_of_cells_with_center_points_within_their_bounds);
-  
-  /******************* TESTING ********************/
-
-  
-  double cell_corners_in_3D[30] = {1.5, 0, 1.5, 0, 1.5, 0, -1.5, 0, -1.5, 0, -1.5, 0, 1.5, 0, -1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-  double cell_corners_in_2D[20];
-  double center_point_in_3D[3] = {0.5, 0, 0.5};
-  double center_point_in_2D[2];
 
-  printf("\n\n\n\n\nTesting the projection on the cell plane:\n\n");
+      /* Checking for convexity of the cell. */
 
-  printf("The vertex coordinates in Euclidean space are: (%f, %f, %f), (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n\n", cell_corners_in_3D[0], cell_corners_in_3D[1], cell_corners_in_3D[2], cell_corners_in_3D[3], cell_corners_in_3D[4], cell_corners_in_3D[5], cell_corners_in_3D[6], cell_corners_in_3D[7], cell_corners_in_3D[8], cell_corners_in_3D[9], cell_corners_in_3D[10], cell_corners_in_3D[11]);
- 
-  printf("The center point coordinates in Euclidean space are: (%f, %f, %f)\n\n", center_point_in_3D[0], center_point_in_3D[1], center_point_in_3D[2]);
+      if ( is_simple_polygon_convex(cell_corners_plane_projection, actual_number_of_corners +1) )
+	no_convex_cells += 1;
+     
+      /* Checking the arrangement or direction of cell vertices. */
 
-  struct axis z_axis = compute_the_new_z_axis(cell_corners_in_3D);
+      polygon_area = calculate_the_polygon_area(cell_corners_plane_projection, actual_number_of_corners + 1);
+      bool is_clockwise = are_polygon_vertices_arranged_in_clockwise_order(polygon_area);
+            
+      /* If the direction of the vertices was flipped during the projection onto the two-dimensional plane, the previous result needs to be inverted now. */
 
-  printf("The new z-axis is: (%f, %f, %f)\n\n", z_axis.axis_vector[0], z_axis.axis_vector[1], z_axis.axis_vector[2]);
-
-  struct axis y_axis = compute_the_new_y_axis(z_axis);
-
-  printf("The new y-axis is: (%f, %f, %f)\n\n", y_axis.axis_vector[0], y_axis.axis_vector[1], y_axis.axis_vector[2]);
+      if ( invert_result )
+        {
+          if ( is_clockwise )
+            is_clockwise = false;
+          else
+            is_clockwise = true;
+        }
 
-  struct axis x_axis = compute_the_new_x_axis(z_axis, y_axis);
- 
-  printf("The new x-axis is: (%f, %f, %f)\n\n", x_axis.axis_vector[0], x_axis.axis_vector[1], x_axis.axis_vector[2] );
+      /* The overall counter of (counter)clockwise cells is increased by one. */
 
-  project_Euclidean_corner_coordinates_onto_the_cell_plane(x_axis, y_axis, &cell_corners_in_3D, &cell_corners_in_2D, 4);
+      if ( is_clockwise )
+	no_clockwise_cells += 1;
+      else
+	no_counterclockwise_cells +=1;
       
-  printf("The new vertex coordinates are:(%f, %f), (%f, %f), (%f, %f), (%f, %f)\n\n", cell_corners_in_2D[0], cell_corners_in_2D[1], cell_corners_in_2D[2], cell_corners_in_2D[3], cell_corners_in_2D[4], cell_corners_in_2D[5], cell_corners_in_2D[6], cell_corners_in_2D[7]);
+      /* The winding numbers algorithm is used to test whether the presumed center point is within the bounds of the cell. */
+        
+      winding_number = winding_numbers_algorithm(cell_corners_plane_projection, actual_number_of_corners + 1, center_point_plane_projection);
 
-  project_Euclidean_center_coordinates_onto_the_cell_plane(x_axis, y_axis, &center_point_in_3D, &center_point_in_2D);
 
-  printf("The new center point coordinates are: (%f, %f)\n\n", center_point_in_2D[0], center_point_in_2D[1]);
+      if ( winding_number == 0 )
+	no_of_cells_with_center_points_out_of_bounds += 1;
+    }
 
-  double double_the_area = calculate_twice_the_polygon_area(cell_corners_in_2D, 4);
- 
-  printf("Are the vertices arranged in clockwise order? %u\n\n", are_polygon_vertices_arranged_in_clockwise_order(double_the_area));
+  int no_nonunique_cells = gridsize - no_unique_center_points;
+  int no_nonconvex_cells =  (int) gridsize - no_convex_cells;
 
-  printf("Is the cell convex? %u\n\n", is_simple_polygon_convex(cell_corners_in_2D, 4));
+  for ( int i = 2; i < ncorner; i++ )
+    if ( no_cells_with_a_specific_no_of_corners[i] )
+      cdoPrintBlue("%9d cells have %d vertices", no_cells_with_a_specific_no_of_corners[i], i + 1);
 
-  int winding_number = winding_numbers_algorithm_without_printfs(cell_corners_in_2D, 4, center_point_in_2D);
+  if ( no_of_cells_with_duplicates )
+    cdoPrintBlue("%9d cells have duplicate vertices", no_of_cells_with_duplicates);
 
-  printf("If the winding number is 0 the presumed center point is outside the bounds of the cell. The winding number is: %d\n\n", winding_number);
- 
+  if ( no_nonunique_cells )
+    cdoPrintRed("%9d cells are not unique", no_nonunique_cells);
+  
+  if ( no_nonconvex_cells )
+    cdoPrintRed("%9d cells are non-convex", no_nonconvex_cells);
 
+  if ( no_clockwise_cells )
+    cdoPrintRed("%9d cells have their vertices arranged in a clockwise order", no_clockwise_cells);
+  
+  if ( no_of_cells_with_center_points_out_of_bounds )
+    cdoPrintRed("%9d cells have their center points located outside their boundaries", no_of_cells_with_center_points_out_of_bounds);
 
+  cdoPrint("");
 }
 
+
 void *Verifygrid(void *argument)
 {
-  bool lgrid_gen_bounds = false, luse_grid_corner = true;
-  double *grid_corner_lat = NULL, *grid_corner_lon = NULL;
   char units[CDI_MAX_NAME];
 
   cdoInitialize(argument);
 
-  int VERIFYGRID     = cdoOperatorAdd("verifygrid",  0,   0, NULL);
-  int VERIFYGRIDTEST = cdoOperatorAdd("verifygridtest",  0,   0, NULL);
+  int VERIFYGRID = cdoOperatorAdd("verifygrid",  0,   0, NULL);
 
   int operatorID = cdoOperatorID();
 
@@ -1103,85 +688,108 @@ void *Verifygrid(void *argument)
 
   int vlistID = streamInqVlist(streamID);
 
-  int gridID  = vlistInqVarGrid(vlistID, 0);
-
-  if ( gridInqType(gridID) == GRID_GME ) gridID = gridToUnstructured(gridID, 1);
-
-  if ( gridInqType(gridID) != GRID_UNSTRUCTURED && gridInqType(gridID) != GRID_CURVILINEAR )
+  int ngrids = vlistNgrids(vlistID);
+  for ( int gridno = 0; gridno < ngrids; ++gridno )
     {
-      gridID = gridToCurvilinear(gridID, 1);
-      lgrid_gen_bounds = TRUE;
-    }
+      bool lgeo = true;
+      bool lgrid_gen_bounds = false, luse_grid_corner = true;
 
-  int gridsize = gridInqSize(gridID);
-  /*
-  if ( gridInqMaskGME(gridID, NULL) )
-    {
-      int *grid_mask = (int*) Malloc(gridsize*sizeof(int));
-      gridInqMaskGME(gridID, grid_mask);
-      free(grid_mask);
-    }
-  */
-  int ncorner = 4;
-  if ( gridInqType(gridID) == GRID_UNSTRUCTURED )
-    ncorner = gridInqNvertex(gridID);
+      int gridID = vlistGrid(vlistID, gridno);
+      int gridtype = gridInqType(gridID);
+
+      if ( gridtype == GRID_GME ) gridID = gridToUnstructured(gridID, 1);
 
-  double *grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
-  double *grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
+      if ( gridtype != GRID_UNSTRUCTURED && gridtype != GRID_CURVILINEAR )
+        {
+          if ( gridtype == GRID_GENERIC || gridtype == GRID_SPECTRAL )
+            {
+              lgeo = false;
+            }
+          else
+            {
+              gridID = gridToCurvilinear(gridID, 1);
+              lgrid_gen_bounds = true;
+            }
+        }
 
-  gridInqYvals(gridID, grid_center_lat);
-  gridInqXvals(gridID, grid_center_lon);
+      int gridsize = gridInqSize(gridID);
+      /*
+        if ( gridInqMaskGME(gridID, NULL) )
+        {
+        int *grid_mask = (int*) Malloc(gridsize*sizeof(int));
+        gridInqMaskGME(gridID, grid_mask);
+        Free(grid_mask);
+        }
+      */
+      if ( lgeo )
+        {
+          double *grid_corner_lat = NULL, *grid_corner_lon = NULL;
+          int ncorner = 4;
+          if ( gridInqType(gridID) == GRID_UNSTRUCTURED )
+            ncorner = gridInqNvertex(gridID);
 
-  /* Convert lat/lon units if required */
-  gridInqXunits(gridID, units);
-  grid_to_degree(units, gridsize, grid_center_lon, "grid center lon");
-  gridInqYunits(gridID, units);
-  grid_to_degree(units, gridsize, grid_center_lat, "grid center lat");
+          double *grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
+          double *grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
 
-  if ( luse_grid_corner )
-    {
-      if ( ncorner == 0 ) cdoAbort("grid corner missing!");
-      int nalloc = ncorner*gridsize;
-      grid_corner_lat = (double*) Realloc(grid_corner_lat, nalloc*sizeof(double));
-      grid_corner_lon = (double*) Realloc(grid_corner_lon, nalloc*sizeof(double));
-
-      if ( gridInqYbounds(gridID, NULL) && gridInqXbounds(gridID, NULL) )
-	{
-	  gridInqYbounds(gridID, grid_corner_lat);
-	  gridInqXbounds(gridID, grid_corner_lon);
-	}
-      else
-	{
-	  if ( lgrid_gen_bounds )
-	    {
-	      char xunitstr[CDI_MAX_NAME];
-	      char yunitstr[CDI_MAX_NAME];
-	      gridInqXunits(gridID, xunitstr);
-	      gridInqYunits(gridID, yunitstr);
-	    }
-	  else
-	    cdoAbort("Grid corner missing!");
-	}
+          gridInqYvals(gridID, grid_center_lat);
+          gridInqXvals(gridID, grid_center_lon);
 
+          /* Convert lat/lon units if required */
+          gridInqXunits(gridID, units);
+          grid_to_degree(units, gridsize, grid_center_lon, "grid center lon");
+          gridInqYunits(gridID, units);
+          grid_to_degree(units, gridsize, grid_center_lat, "grid center lat");
 
-      /* Note: using units from latitude instead from bounds */
-      grid_to_degree(units, ncorner*gridsize, grid_corner_lon, "grid corner lon");
-      grid_to_degree(units, ncorner*gridsize, grid_corner_lat, "grid corner lat");
+          if ( luse_grid_corner )
+            {
+              if ( ncorner == 0 ) cdoAbort("grid corner missing!");
+              int nalloc = ncorner*gridsize;
+              grid_corner_lat = (double*) Realloc(grid_corner_lat, nalloc*sizeof(double));
+              grid_corner_lon = (double*) Realloc(grid_corner_lon, nalloc*sizeof(double));
+          
+              if ( gridInqYbounds(gridID, NULL) && gridInqXbounds(gridID, NULL) )
+                {
+                  gridInqYbounds(gridID, grid_corner_lat);
+                  gridInqXbounds(gridID, grid_corner_lon);
+                }
+              else
+                {
+                  if ( lgrid_gen_bounds )
+                    {
+                      char xunitstr[CDI_MAX_NAME];
+                      char yunitstr[CDI_MAX_NAME];
+                      gridInqXunits(gridID, xunitstr);
+                      gridInqYunits(gridID, yunitstr);
+                    }
+                  else
+                    cdoAbort("Grid corner missing!");
+                }
+          
+              /* Note: using units from latitude instead from bounds */
+              grid_to_degree(units, ncorner*gridsize, grid_corner_lon, "grid corner lon");
+              grid_to_degree(units, ncorner*gridsize, grid_corner_lat, "grid corner lat");
+            }
+      
+          if ( operatorID == VERIFYGRID )
+            verify_grid(gridtype, gridsize, gridno, ngrids, ncorner, grid_center_lon, grid_center_lat, grid_corner_lon, grid_corner_lat);
 
+          if ( grid_center_lon ) Free(grid_center_lon);
+          if ( grid_center_lat ) Free(grid_center_lat);
+          if ( grid_corner_lon ) Free(grid_corner_lon);
+          if ( grid_corner_lat ) Free(grid_corner_lat);
+        }
+      else
+        {
+          if ( ngrids == 1 )
+            cdoPrintBlue("Grid consists of %d points (type: %s)", gridsize, gridNamePtr(gridtype));
+          else
+            cdoPrintBlue("Grid no %u (of %u) consists of %d points (type: %s)", gridno + 1, ngrids, gridsize, gridNamePtr(gridtype));
+          cdoPrint("");
+        }
     }
 
   streamClose(streamID);
-
-  if ( operatorID == VERIFYGRID )
-    verify_grid(gridsize, ncorner, grid_center_lon, grid_center_lat, grid_corner_lon, grid_corner_lat);
-  else
-    verify_grid_test(gridsize, ncorner, grid_center_lon, grid_center_lat, grid_corner_lon, grid_corner_lat);
-
-  if ( grid_center_lon ) Free(grid_center_lon);
-  if ( grid_center_lat ) Free(grid_center_lat);
-  if ( grid_corner_lon ) Free(grid_corner_lon);
-  if ( grid_corner_lat ) Free(grid_corner_lat);
-
+  
   cdoFinish();
 
   return 0;
diff --git a/src/Vertintap.c b/src/Vertintap.c
index 5135a0e..656dbbc 100644
--- a/src/Vertintap.c
+++ b/src/Vertintap.c
@@ -33,9 +33,9 @@
 #include "stdnametable.h"
 
 static
-int is_height_axis(int zaxisID, int nlevel)
+bool is_height_axis(int zaxisID, int nlevel)
 {
-  int isheight = FALSE;
+  bool isheight = false;
   if ( nlevel > 1 )
     {
       if ( zaxisInqType(zaxisID) == ZAXIS_REFERENCE )
@@ -45,12 +45,12 @@ int is_height_axis(int zaxisID, int nlevel)
           zaxisInqUnits(zaxisID, units);
           zaxisInqStdname(zaxisID, stdname);
           if ( strcmp(stdname, "height") == 0 && *units == 0 )
-            isheight = TRUE;
+            isheight = true;
         }
     }
   return isheight;
 }
-
+/*
 static
 int is_hybrid_axis(int zaxisID, int nlevel)
 {
@@ -59,20 +59,19 @@ int is_hybrid_axis(int zaxisID, int nlevel)
        nlevel > 1 ) ishybrid = TRUE;
   return ishybrid;
 }
-
+*/
 
 void *Vertintap(void *argument)
 {
   enum {func_pl, func_hl};
   enum {type_lin, type_log};
-  int recID, nrecs;
+  int nrecs;
   int i, k, offset;
   int varID, levelID;
-  int zaxisIDp, zaxisIDh = -1, nzaxis;
+  int zaxisIDp, zaxisIDh = -1;
   int gridID, zaxisID;
   int nhlev = 0, nhlevf = 0, nhlevh = 0, nlevel;
   int *vert_index = NULL;
-  int nvct;
   int apressID = -1, dpressID = -1;
   int psID = -1, tempID = -1;
   int param;
@@ -80,6 +79,7 @@ void *Vertintap(void *argument)
   int *pnmiss = NULL;
   char paramstr[32];
   char stdname[CDI_MAX_NAME];
+  char varname[CDI_MAX_NAME];
   double minval, maxval;
   double missval;
   double *vct = NULL;
@@ -87,13 +87,14 @@ void *Vertintap(void *argument)
   double *ps_prog = NULL, *full_press = NULL, *dpress = NULL;
   double *hyb_press = NULL;
   int Extrapolate = 0;
-  int mono_level;
   LIST *flist = listNew(FLT_LIST);
 
   cdoInitialize(argument);
 
   int AP2PL     = cdoOperatorAdd("ap2pl",     func_pl, type_lin, "pressure levels in pascal");
   int AP2PLX    = cdoOperatorAdd("ap2plx",    func_pl, type_lin, "pressure levels in pascal");
+  int AP2HL     = cdoOperatorAdd("ap2hl",     func_hl, type_lin, "height levels in meter");
+  int AP2HLX    = cdoOperatorAdd("ap2hlx",    func_hl, type_lin, "height levels in meter");
   int AP2PL_LP  = cdoOperatorAdd("ap2pl_lp",  func_pl, type_log, "pressure levels in pascal");
   int AP2PLX_LP = cdoOperatorAdd("ap2plx_lp", func_pl, type_log, "pressure levels in pascal");
 
@@ -101,7 +102,7 @@ void *Vertintap(void *argument)
   int operfunc   = cdoOperatorF1(operatorID);
   int opertype   = cdoOperatorF2(operatorID);
 
-  if ( operatorID == AP2PL || operatorID == AP2PL_LP )
+  if ( operatorID == AP2PL || operatorID == AP2HL || operatorID == AP2PL_LP )
     {
       char *envstr = getenv("EXTRAPOLATE");
 
@@ -112,7 +113,7 @@ void *Vertintap(void *argument)
             cdoPrint("Extrapolation of missing values enabled!");
 	}
     }
-  else if ( operatorID == AP2PLX || operatorID == AP2PLX_LP )
+  else if ( operatorID == AP2PLX ||  operatorID == AP2HLX || operatorID == AP2PLX_LP )
     {
       Extrapolate = 1;
     }
@@ -123,15 +124,25 @@ void *Vertintap(void *argument)
   double *plev = NULL;
   if ( operatorArgc() == 1 && strcmp(operatorArgv()[0], "default") == 0 )
     {
-      /*
-      double stdlev[] = {100000, 92500, 85000, 77500, 70000, 60000, 50000, 40000, 30000, 25000, 20000,
-                          15000, 10000, 7000, 5000, 3000, 2000, 1000, 700, 500, 300, 200, 100, 50, 20, 10};
-      */
-      double stdlev[] = {100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000,
-                          10000,  7000,  5000,  3000,  2000, 1000 };
-      nplev = sizeof(stdlev)/sizeof(*stdlev);
-      plev  = (double *) Malloc(nplev*sizeof(double));
-      for ( i = 0; i < nplev; ++i ) plev[i] = stdlev[i];
+      if ( operfunc == func_hl )
+        {
+          double stdlev[] = { 10, 50, 100, 500, 1000, 5000, 10000, 15000, 20000, 25000, 30000 };
+          nplev = sizeof(stdlev)/sizeof(*stdlev);
+          plev  = (double *) Malloc(nplev*sizeof(double));
+          for ( i = 0; i < nplev; ++i ) plev[i] = stdlev[i];
+        }
+      else
+        {
+          /*
+            double stdlev[] = {100000, 92500, 85000, 77500, 70000, 60000, 50000, 40000, 30000, 25000, 20000,
+            15000, 10000, 7000, 5000, 3000, 2000, 1000, 700, 500, 300, 200, 100, 50, 20, 10};
+          */
+          double stdlev[] = {100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000,
+                             10000,  7000,  5000,  3000,  2000, 1000 };
+          nplev = sizeof(stdlev)/sizeof(*stdlev);
+          plev  = (double *) Malloc(nplev*sizeof(double));
+          for ( i = 0; i < nplev; ++i ) plev[i] = stdlev[i];
+        }
     }
   else
     {
@@ -156,119 +167,71 @@ void *Vertintap(void *argument)
     zaxisIDp = zaxisCreate(ZAXIS_PRESSURE, nplev);
 
   zaxisDefLevels(zaxisIDp, plev);
-  nzaxis  = vlistNzaxis(vlistID1);
 
-  int lheight = FALSE;
-  for ( i = 0; i < nzaxis; i++ )
+  int nvars = vlistNvars(vlistID1);
+
+  for ( varID = 0; varID < nvars; varID++ )
     {
-      mono_level = TRUE;
-      zaxisID = vlistZaxis(vlistID1, i);
-      nlevel  = zaxisInqSize(zaxisID);
+      vlistInqVarStdname(vlistID1, varID, stdname);
+      strtolower(stdname);
 
-      if ( is_height_axis(zaxisID, nlevel) )
-        {
-	  double *level = (double *) Malloc(nlevel*sizeof(double));
-	  zaxisInqLevels(zaxisID, level);
-	  int l;
-	  for ( l = 0; l < nlevel; l++ )
-	    {
-	      if ( (l+1) != (int) (level[l]+0.5) ) break;
-	    }
-	  if ( l == nlevel ) mono_level = TRUE; 
-	  Free(level);          
-        }
-      
-      if ( is_height_axis(zaxisID, nlevel) && mono_level )
-        {
-          lheight  = TRUE;
-          zaxisIDh = zaxisID;
-          nhlev    = nlevel;
-          nhlevf   = nhlev;
-          nhlevh   = nhlevf + 1;
-
-          vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-          break;
-        }
+      if      ( strcmp(stdname, var_stdname(surface_air_pressure)) == 0 ) psID = varID; 
+      else if ( strcmp(stdname, var_stdname(air_pressure))         == 0 ) apressID = varID; 
+      else if ( strcmp(stdname, var_stdname(pressure_thickness))   == 0 ) dpressID = varID; 
+      else if ( strcmp(stdname, var_stdname(air_temperature))      == 0 ) tempID = varID; 
     }
 
-  if ( ! lheight ) { // old version, not needed anymore!!
-  int lhavevct = FALSE;
-  for ( i = 0; i < nzaxis; i++ )
+  if ( cdoVerbose )
     {
-      /* mono_level = FALSE; */
-      mono_level = TRUE;
-      zaxisID = vlistZaxis(vlistID1, i);
-      nlevel  = zaxisInqSize(zaxisID);
+      cdoPrint("Found:");
+      if ( psID      != -1 ) cdoPrint("  %s", var_stdname(surface_air_pressure));
+      if ( apressID  != -1 ) cdoPrint("  %s", var_stdname(air_pressure));
+      if ( dpressID  != -1 ) cdoPrint("  %s", var_stdname(pressure_thickness));
+      if ( tempID    != -1 ) cdoPrint("  %s", var_stdname(air_temperature));
+    }
 
-      if ( is_hybrid_axis(zaxisID, nlevel) )
-	{
-	  double *level = (double *) Malloc(nlevel*sizeof(double));
-	  zaxisInqLevels(zaxisID, level);
-	  int l;
-	  for ( l = 0; l < nlevel; l++ )
-	    {
-	      if ( (l+1) != (int) (level[l]+0.5) ) break;
-	    }
-	  if ( l == nlevel ) mono_level = TRUE; 
-	  Free(level);
-	}
+  if ( apressID == -1 ) cdoAbort("%s not found!", var_stdname(air_pressure));
 
-      if ( is_hybrid_axis(zaxisID, nlevel) && mono_level )
-	{
-	  nvct = zaxisInqVctSize(zaxisID);
-	  if ( nlevel == (nvct/2 - 1) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  lhavevct = TRUE;
-		  zaxisIDh = zaxisID;
-		  nhlev    = nlevel;
-		  nhlevf   = nhlev;
-		  nhlevh   = nhlevf + 1;
-	      
-		  vct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID, vct);
-
-		  vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	      else
-		{
-		  if ( memcmp(vct, zaxisInqVctPtr(zaxisID), nvct*sizeof(double)) == 0 )
-		    vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	    }
-	  else if ( nlevel == (nvct/2) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  lhavevct = TRUE;
-		  zaxisIDh = zaxisID;
-		  nhlev    = nlevel;
-		  nhlevf   = nhlev - 1;
-		  nhlevh   = nhlev;
-	      
-		  vct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID, vct);
-
-		  vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	      else
-		{
-		  if ( memcmp(vct, zaxisInqVctPtr(zaxisID), nvct*sizeof(double)) == 0 )
-		    vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	    }
-	}
+  int nzaxis = vlistNzaxis(vlistID1);
+  for ( i = 0; i < nzaxis; i++ )
+    {
+      zaxisID = vlistZaxis(vlistID1, i);
+      if ( zaxisID == vlistInqVarZaxis(vlistID1, apressID) )
+        {
+          bool mono_level = true;
+          nlevel  = zaxisInqSize(zaxisID);
+
+          if ( is_height_axis(zaxisID, nlevel) )
+            {
+              double *level = (double *) Malloc(nlevel*sizeof(double));
+              zaxisInqLevels(zaxisID, level);
+              int l;
+              for ( l = 0; l < nlevel; l++ )
+                {
+                  if ( (l+1) != (int) (level[l]+0.5) ) break;
+                }
+              if ( l == nlevel ) mono_level = true; 
+              Free(level);          
+            }
+      
+          if ( is_height_axis(zaxisID, nlevel) && mono_level )
+            {
+              zaxisIDh = zaxisID;
+              nhlev    = nlevel;
+              nhlevf   = nhlev;
+              nhlevh   = nhlevf + 1;
+
+              vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
+              break;
+            }
+        }
     }
-  }
   
-  int nvars = vlistNvars(vlistID1);
-
-  int vars[nvars];
+  bool vars[nvars];
   double *vardata1[nvars];
   double *vardata2[nvars];
   int *varnmiss[nvars];
-  int varinterp[nvars];
+  bool varinterp[nvars];
 
   int maxlev = nhlevh > nplev ? nhlevh : nplev;
 
@@ -324,50 +287,38 @@ void *Vertintap(void *argument)
       zaxisID  = vlistInqVarZaxis(vlistID1, varID);
       nlevel   = zaxisInqSize(zaxisID);
 
-      vlistInqVarStdname(vlistID1, varID, stdname);
-      strtolower(stdname);
-
-      if      ( strcmp(stdname, var_stdname(surface_air_pressure)) == 0 ) psID = varID; 
-      else if ( strcmp(stdname, var_stdname(air_pressure))         == 0 ) apressID = varID; 
-      else if ( strcmp(stdname, var_stdname(pressure_thickness))   == 0 ) dpressID = varID; 
-      else if ( strcmp(stdname, var_stdname(air_temperature))      == 0 ) tempID = varID; 
-
       if ( gridInqType(gridID) == GRID_SPECTRAL )
 	cdoAbort("Spectral data unsupported!");
 
       vardata1[varID] = (double *) Malloc(gridsize*nlevel*sizeof(double));
-
+           
       if ( zaxisID == zaxisIDh )
 	{
-	  varinterp[varID] = TRUE;
+	  varinterp[varID] = true;
 	  vardata2[varID]  = (double *) Malloc(gridsize*nplev*sizeof(double));
 	  varnmiss[varID]  = (int *) Malloc(maxlev*sizeof(int));
 	  memset(varnmiss[varID], 0, maxlev*sizeof(int));
 	}
       else
 	{
-	  varinterp[varID] = FALSE;
+          vlistInqVarName(vlistID1, varID, varname);
+
+          if ( is_height_axis(zaxisID, nlevel) && nlevel == nhlevh )
+            cdoWarning("Interpolation from half level not supported, parameter %s not interpolated!", varname);
+          
+	  varinterp[varID] = false;
 	  vardata2[varID]  = vardata1[varID];
 	  varnmiss[varID]  = (int *) Malloc(nlevel*sizeof(int));
 	}
     }
-
-  if ( cdoVerbose )
-    {
-      cdoPrint("Found:");
-      if ( psID      != -1 ) cdoPrint("  %s", var_stdname(surface_air_pressure));
-      if ( apressID  != -1 ) cdoPrint("  %s", var_stdname(air_pressure));
-      if ( dpressID  != -1 ) cdoPrint("  %s", var_stdname(pressure_thickness));
-      if ( tempID    != -1 ) cdoPrint("  %s", var_stdname(air_temperature));
-    }
-
-  if ( apressID == -1 ) cdoAbort("%s not found!", var_stdname(air_pressure));
+  
   if ( zaxisIDh != -1 && psID == -1 && dpressID )
-    cdoWarning("Surface pressure not found - set to upper level of %s!", var_stdname(air_pressure));
+    cdoWarning("Surface pressure not found - set to vertical sum of %s!", var_stdname(pressure_thickness));
+  //  cdoWarning("Surface pressure not found - set to upper level of %s!", var_stdname(air_pressure));
 
   for ( varID = 0; varID < nvars; ++varID )
     {
-      if ( varinterp[varID] == TRUE && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
+      if ( varinterp[varID] && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
 	vlistDefVarTsteptype(vlistID2, varID, TSTEP_INSTANT);
     }
 
@@ -380,7 +331,7 @@ void *Vertintap(void *argument)
     {
       for ( varID = 0; varID < nvars; ++varID )
 	{
-          vars[varID] = FALSE;
+          vars[varID] = false;
 	  nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
 	  for ( levelID = 0; levelID < nlevel; levelID++ )
 	    varnmiss[varID][levelID] = 0;
@@ -390,7 +341,7 @@ void *Vertintap(void *argument)
 
       streamDefTimestep(streamID2, tsID);
 
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	{
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  /*
@@ -407,11 +358,11 @@ void *Vertintap(void *argument)
 
 	  streamReadRecord(streamID1, single1, &varnmiss[varID][levelID]);
 
-	  vars[varID] = TRUE;
+	  vars[varID] = true;
 	}
 
       for ( varID = 0; varID < nvars; varID++ )
-	if ( varinterp[varID] == TRUE ) vars[varID] = TRUE;
+	if ( varinterp[varID]  ) vars[varID] = true;
 
       if ( zaxisIDh != -1 )
 	{
diff --git a/src/Vertintml.c b/src/Vertintml.c
index 5a5087b..c873d64 100644
--- a/src/Vertintml.c
+++ b/src/Vertintml.c
@@ -59,13 +59,10 @@ void *Vertintml(void *argument)
   char varname[CDI_MAX_NAME], stdname[CDI_MAX_NAME];
   double minval, maxval;
   double missval;
-  double *vct = NULL;
   double *rvct = NULL; /* reduced VCT for LM */
   double *single1, *single2;
   double *sgeopot = NULL, *ps_prog = NULL, *full_press = NULL, *half_press = NULL;
-  double *hyb_press = NULL;
   int Extrapolate = 0;
-  int mono_level;
   int instNum, tableNum;
   int useTable;
   gribcode_t gribcodes = {0};
@@ -108,15 +105,25 @@ void *Vertintml(void *argument)
   double *plev = NULL;
   if ( operatorArgc() == 1 && strcmp(operatorArgv()[0], "default") == 0 )
     {
-      /*
-      double stdlev[] = {100000, 92500, 85000, 77500, 70000, 60000, 50000, 40000, 30000, 25000, 20000,
-                          15000, 10000, 7000, 5000, 3000, 2000, 1000, 700, 500, 300, 200, 100, 50, 20, 10};
-      */
-      double stdlev[] = {100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000,
-                          10000,  7000,  5000,  3000,  2000, 1000 };
-      nplev = sizeof(stdlev)/sizeof(*stdlev);
-      plev  = (double *) Malloc(nplev*sizeof(double));
-      for ( i = 0; i < nplev; ++i ) plev[i] = stdlev[i];
+      if ( operfunc == func_hl )
+        {
+          double stdlev[] = { 10, 50, 100, 500, 1000, 5000, 10000, 15000, 20000, 25000, 30000 };
+          nplev = sizeof(stdlev)/sizeof(*stdlev);
+          plev  = (double *) Malloc(nplev*sizeof(double));
+          for ( i = 0; i < nplev; ++i ) plev[i] = stdlev[i];
+        }
+      else
+        {
+          /*
+            double stdlev[] = {100000, 92500, 85000, 77500, 70000, 60000, 50000, 40000, 30000, 25000, 20000,
+            15000, 10000, 7000, 5000, 3000, 2000, 1000, 700, 500, 300, 200, 100, 50, 20, 10};
+          */
+          double stdlev[] = {100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000,
+                             10000,  7000,  5000,  3000,  2000, 1000 };
+          nplev = sizeof(stdlev)/sizeof(*stdlev);
+          plev  = (double *) Malloc(nplev*sizeof(double));
+          for ( i = 0; i < nplev; ++i ) plev[i] = stdlev[i];
+        }
     }
   else
     {
@@ -141,142 +148,24 @@ void *Vertintml(void *argument)
     zaxisIDp = zaxisCreate(ZAXIS_PRESSURE, nplev);
 
   zaxisDefLevels(zaxisIDp, plev);
-  int nzaxis  = vlistNzaxis(vlistID1);
-  int lhavevct = FALSE;
-  for ( i = 0; i < nzaxis; i++ )
-    {
-      /* mono_level = FALSE; */
-      mono_level = TRUE;
-      zaxisID = vlistZaxis(vlistID1, i);
-      nlevel  = zaxisInqSize(zaxisID);
-
-      if ( (zaxisInqType(zaxisID) == ZAXIS_HYBRID || zaxisInqType(zaxisID) == ZAXIS_HYBRID_HALF) &&
-	   nlevel > 1 )
-	{
-	  double level[nlevel];
-	  zaxisInqLevels(zaxisID, level);
-	  int l;
-	  for ( l = 0; l < nlevel; l++ )
-	    {
-	      if ( (l+1) != (int) (level[l]+0.5) ) break;
-	    }
-	  if ( l == nlevel ) mono_level = TRUE; 
-	}
-
-      if ( (zaxisInqType(zaxisID) == ZAXIS_HYBRID || zaxisInqType(zaxisID) == ZAXIS_HYBRID_HALF) &&
-	   nlevel > 1 && mono_level )
-	{
-	  nvct = zaxisInqVctSize(zaxisID);
-	  if ( nlevel == (nvct/2 - 1) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  lhavevct = TRUE;
-		  zaxisIDh = zaxisID;
-		  nhlev    = nlevel;
-		  nhlevf   = nhlev;
-		  nhlevh   = nhlev + 1;
-
-		  vct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID, vct);
-
-		  vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	      else
-		{
-		  if ( memcmp(vct, zaxisInqVctPtr(zaxisID), nvct*sizeof(double)) == 0 )
-		    vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	    }
-	  else if ( nlevel == (nvct/2) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  lhavevct = TRUE;
-		  zaxisIDh = zaxisID;
-		  nhlev    = nlevel;
-		  nhlevf   = nhlev - 1;
-		  nhlevh   = nhlev;
-	      
-		  vct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID, vct);
-
-		  vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	      else
-		{
-		  if ( memcmp(vct, zaxisInqVctPtr(zaxisID), nvct*sizeof(double)) == 0 )
-		    vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	    }
-	  else if ( nlevel == (nvct - 4 - 1) )
-	    {
-	      if ( lhavevct == FALSE )
-		{
-		  int vctsize;
-		  int voff = 4;
-		  
-		  rvct = (double*) Malloc(nvct*sizeof(double));
-		  zaxisInqVct(zaxisID, rvct);
-
-		  if ( (int)(rvct[0]+0.5) == 100000 && rvct[voff] < rvct[voff+1] )
-		    {
-		      lhavevct = TRUE;
-		      zaxisIDh = zaxisID;
-		      nhlev    = nlevel;
-		      nhlevf   = nhlev;
-		      nhlevh   = nhlev + 1;
 
-		      vctsize = 2*nhlevh;
-		      vct = (double*) Malloc(vctsize*sizeof(double));
+  double *vct = vlist_read_vct(vlistID1, &zaxisIDh, &nvct, &nhlev, &nhlevf, &nhlevh);
 
-		      vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-
-		      /* calculate VCT for LM */
-
-		      for ( i = 0; i < vctsize/2; i++ )
-			{
-			  if ( rvct[voff+i] >= rvct[voff] && rvct[voff+i] <= rvct[3] )
-			    {
-			      vct[i] = rvct[0]*rvct[voff+i];
-			      vct[vctsize/2+i] = 0;
-			    }
-			  else
-			    {
-			      vct[i] = (rvct[0]*rvct[3]*(1-rvct[voff+i]))/(1-rvct[3]);
-			      vct[vctsize/2+i] = (rvct[voff+i]-rvct[3])/(1-rvct[3]);
-			    }
-			}
-		      
-		      if ( cdoVerbose )
-			{
-			  for ( i = 0; i < vctsize/2; i++ )
-			    fprintf(stdout, "%5d %25.17f %25.17f\n", i, vct[i], vct[vctsize/2+i]);
-			}
-		    }
-		}
-	      else
-		{
-		  if ( memcmp(rvct, zaxisInqVctPtr(zaxisID), nvct*sizeof(double)) == 0 )
-		    vlistChangeZaxisIndex(vlistID2, i, zaxisIDp);
-		}
-	    }
-	}
-    }
+  vlist_change_hybrid_zaxis(vlistID1, vlistID2, zaxisIDh, zaxisIDp);
 
   int psvarID = -1;
-  int linvertvct = FALSE;
-  if ( lhavevct && nvct && nvct%2 == 0 )
+  bool linvertvct = false;
+  if ( vct && nvct && nvct%2 == 0 )
     {
       psvarID = vlist_get_psvarid(vlistID1, zaxisIDh);
 
       for ( i = nvct/2+1; i < nvct; i++ )
         if ( vct[i] > vct[i-1] ) break;
 
-      if ( i == nvct ) linvertvct = TRUE;
+      if ( i == nvct ) linvertvct = true;
     }
 
-  if ( cdoVerbose ) cdoPrint("linvertvct = %d", linvertvct);
+  if ( cdoVerbose ) cdoPrint("linvertvct = %d", (int) linvertvct);
 
   if ( linvertvct )
     {
@@ -646,6 +535,7 @@ void *Vertintml(void *argument)
 		      nlevel = nhlevf;
 		    }
 		  */
+                  double *hyb_press = NULL;
 		  if ( nlevel == nhlevh )
 		    {
 		      hyb_press = half_press;
diff --git a/src/Wind.c b/src/Wind.c
index 0592310..af2f00e 100644
--- a/src/Wind.c
+++ b/src/Wind.c
@@ -34,20 +34,14 @@
 
 void *Wind(void *argument)
 {
-  int UV2DV, UV2DVL, DV2UV, DV2UVL, DV2PS;
-  int operatorID;
-  int streamID1, streamID2;
-  int nrecs, nvars;
-  int tsID, recID, varID, levelID;
-  int nlev = 0, gridsize;
+  int nrecs;
+  int recID, varID, levelID;
+  int nlev = 0;
   int index, ngrids;
-  int vlistID1, vlistID2;
   int gridIDsp = -1, gridIDgp = -1;
   int gridID1 = -1, gridID2 = -1;
   int gridID;
   int nmiss;
-  int lcopy = FALSE;
-  int taxisID1, taxisID2;
   int nlon, nlat, ntr = -1;
   int code, param;
   int pnum, pcat, pdis;
@@ -56,32 +50,31 @@ void *Wind(void *argument)
   SPTRANS *sptrans = NULL;
   DVTRANS *dvtrans = NULL;
   char varname[CDI_MAX_NAME];
-  double *array1 = NULL;
   double *ivar1 = NULL, *ivar2 = NULL, *ovar1 = NULL, *ovar2 = NULL;
 
   cdoInitialize(argument);
 
-  UV2DV  = cdoOperatorAdd("uv2dv",  0, 0, NULL);
-  UV2DVL = cdoOperatorAdd("uv2dvl", 0, 0, NULL);
-  DV2UV  = cdoOperatorAdd("dv2uv",  0, 0, NULL);
-  DV2UVL = cdoOperatorAdd("dv2uvl", 0, 0, NULL);
-  DV2PS  = cdoOperatorAdd("dv2ps",  0, 0, NULL);
+  bool lcopy = UNCHANGED_RECORD;
 
-  operatorID = cdoOperatorID();
+  int UV2DV  = cdoOperatorAdd("uv2dv",  0, 0, NULL);
+  int UV2DVL = cdoOperatorAdd("uv2dvl", 0, 0, NULL);
+  int DV2UV  = cdoOperatorAdd("dv2uv",  0, 0, NULL);
+  int DV2UVL = cdoOperatorAdd("dv2uvl", 0, 0, NULL);
+  int DV2PS  = cdoOperatorAdd("dv2ps",  0, 0, NULL);
 
-  if ( UNCHANGED_RECORD ) lcopy = TRUE;
+  int operatorID = cdoOperatorID();
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
   /* find variables */
-  nvars = vlistNvars(vlistID2);
+  int nvars = vlistNvars(vlistID2);
   for ( varID = 0; varID < nvars; varID++ )
     {
       param = vlistInqVarParam(vlistID2, varID);
@@ -90,7 +83,7 @@ void *Wind(void *argument)
       if ( operatorID == UV2DV || operatorID == UV2DVL )
 	{
 	  /* search for u and v wind */
-	  if ( code <= 0 )
+	  if ( pdis != 255 || code <= 0 )
 	    {
 	      vlistInqVarName(vlistID1, varID, varname);
 	      strtolower(varname);
@@ -299,12 +292,12 @@ void *Wind(void *argument)
 	}
     }
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  gridsize = vlistGridsizeMax(vlistID1);
-  array1 = (double*) Malloc(gridsize*sizeof(double));
+  int gridsize = vlistGridsizeMax(vlistID1);
+  double *array1 = (double*) Malloc(gridsize*sizeof(double));
 
   if ( varID1 != -1 && varID2 != -1 )
     {
@@ -319,7 +312,7 @@ void *Wind(void *argument)
       ovar2 = (double*) Malloc(nlev*gridsize*sizeof(double));
     }
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/XTimstat.c b/src/XTimstat.c
index b96f292..b9856bd 100644
--- a/src/XTimstat.c
+++ b/src/XTimstat.c
@@ -323,7 +323,7 @@ void *XTimstat(void *argument)
   int otsID = 0;
   int nrecs = streamInqTimestep(streamID1, tsID);
   int maxrecs = nrecs;
-  recinfo_t *recinfo = (recinfo_t *) malloc(maxrecs*sizeof(recinfo_t));
+  recinfo_t *recinfo = (recinfo_t *) Malloc(maxrecs*sizeof(recinfo_t));
   
   tsID++;
   while ( TRUE )
diff --git a/src/YAR.c b/src/YAR.c
index 3c20746..6f6c221 100644
--- a/src/YAR.c
+++ b/src/YAR.c
@@ -739,22 +739,14 @@ void yar_remap_con(field_t *field1, field_t *field2)
 
 void *YAR(void *argument)
 {
-  int YARBIL, YARCON;
-  int operatorID;
-  int streamID1, streamID2;
-  int nrecs, ngrids;
+  int nrecs;
   int index;
-  int tsID, recID, varID, levelID;
-  int gridsize;
-  int vlistID1, vlistID2;
-  int gridID1 = -1, gridID2 = -1;
+  int recID, varID, levelID;
+  int gridID1 = -1;
   int nmiss;
   int xinc = 0, yinc = 0;
   double missval;
   double slon, slat;
-  double *array1 = NULL, *array2 = NULL;
-  field_t field1, field2;
-  int taxisID1, taxisID2;
 
   if ( cdoTimer )
     {
@@ -767,27 +759,29 @@ void *YAR(void *argument)
 
   cdoInitialize(argument);
 
-  YARBIL = cdoOperatorAdd("yarbil",  0, 0, NULL);
-  YARCON = cdoOperatorAdd("yarcon",  0, 0, NULL);
+  int YARBIL = cdoOperatorAdd("yarbil",  0, 0, NULL);
+  int YARCON = cdoOperatorAdd("yarcon",  0, 0, NULL);
 
-  operatorID = cdoOperatorID();
+  int operatorID = cdoOperatorID();
 
   operatorInputArg("grid description file or name");
-  gridID2 = cdoDefineGrid(operatorArgv()[0]);
 
+  field_t field1, field2;
   field_init(&field1);
   field_init(&field2);
 
-  streamID1 = streamOpenRead(cdoStreamName(0));
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  int gridID2 = cdoDefineGrid(operatorArgv()[0]);
 
-  vlistID1 = streamInqVlist(streamID1);
-  vlistID2 = vlistDuplicate(vlistID1);
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
 
-  taxisID1 = vlistInqTaxis(vlistID1);
-  taxisID2 = taxisDuplicate(taxisID1);
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  ngrids = vlistNgrids(vlistID1);
+  int ngrids = vlistNgrids(vlistID1);
   for ( index = 0; index < ngrids; index++ )
     {
       gridID1 = vlistGrid(vlistID1, index);
@@ -801,17 +795,17 @@ void *YAR(void *argument)
       vlistChangeGridIndex(vlistID2, index, gridID2);
     }
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
 
-  gridsize = vlistGridsizeMax(vlistID1);
-  array1   = (double*) Malloc(gridsize*sizeof(double));
+  int gridsize = vlistGridsizeMax(vlistID1);
+  double *array1   = (double*) Malloc(gridsize*sizeof(double));
 
   gridsize = gridInqSize(gridID2);
-  array2   = (double*) Malloc(gridsize*sizeof(double));
+  double *array2   = (double*) Malloc(gridsize*sizeof(double));
 
-  tsID = 0;
+  int tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
       taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Ydrunpctl.c b/src/Ydrunpctl.c
index 3d1654c..7244644 100644
--- a/src/Ydrunpctl.c
+++ b/src/Ydrunpctl.c
@@ -50,7 +50,7 @@ void *Ydrunpctl(void *argument)
   int nmiss;
   int nlevels;
   field_t ***vars1 = NULL, **vars2[NDAY];
-  datetime_t *datetime;
+  cdo_datetime_t *datetime;
   int vdate, vtime;
   int vdates1[NDAY], vtimes1[NDAY];
   int vdates2[NDAY] /*, vtimes2[NDAY]*/;
@@ -114,7 +114,7 @@ void *Ydrunpctl(void *argument)
   field_init(&field);
   field.ptr = (double*) Malloc(gridsize*sizeof(double));
 
-  datetime = (datetime_t*) Malloc((ndates+1)*sizeof(datetime_t));
+  datetime = (cdo_datetime_t*) Malloc((ndates+1)*sizeof(cdo_datetime_t));
   
   vars1 = (field_t ***) Malloc((ndates+1)*sizeof(field_t **));
   
diff --git a/src/Ydrunstat.c b/src/Ydrunstat.c
index a4acdc1..f7bd640 100644
--- a/src/Ydrunstat.c
+++ b/src/Ydrunstat.c
@@ -112,7 +112,7 @@ void *Ydrunstat(void *argument)
   int *recVarID   = (int*) Malloc(nrecords*sizeof(int));
   int *recLevelID = (int*) Malloc(nrecords*sizeof(int));
 
-  datetime_t *datetime = (datetime_t*) Malloc((ndates+1)*sizeof(datetime_t));
+  cdo_datetime_t *datetime = (cdo_datetime_t*) Malloc((ndates+1)*sizeof(cdo_datetime_t));
   
   YDAY_STATS *stats = ydstatCreate(vlistID1);
   field_t ***vars1 = (field_t ***) Malloc((ndates+1)*sizeof(field_t **));
diff --git a/src/after_vertint.c b/src/after_vertint.c
index f750c50..2b63867 100644
--- a/src/after_vertint.c
+++ b/src/after_vertint.c
@@ -14,13 +14,12 @@
 int Mars = 0;
 
 
-void height2pressure(double * restrict phlev, const double * restrict hlev, long nphlev)
+void height2pressure(double *restrict phlev, const double *restrict hlev, long nphlev)
 {
-  long k;
   double exp_arg;
   double height;
 
-  for ( k = 0; k < nphlev; k++ )
+  for ( long k = 0; k < nphlev; k++ )
     {
       height  = hlev[k];
       /*
@@ -36,36 +35,32 @@ void height2pressure(double * restrict phlev, const double * restrict hlev, long
 }
 
 
-void pressure2height(double * restrict hlev, const double * restrict plev, long nphlev)
+void pressure2height(double *restrict hlev, const double *restrict plev, long nphlev)
 {
-  long  k;
-
-  for ( k = 0; k < nphlev; k++ )
+  for ( long k = 0; k < nphlev; k++ )
     {
       hlev[k] = log(plev[k]/SCALESLP)*SCALEHEIGHT;
     }
 }
 
 
-void presh(double * restrict fullp, double * halfp, const double *restrict vct,
+void presh(double *restrict fullp, double * halfp, const double *restrict vct,
 	   const double *restrict ps, long nhlev, long ngp)
 {
-  long i, lh;
-  double zp, ze;
-  double *halfpres = halfp;
-
   if ( ps == NULL )
     {
       fprintf(stderr, "ps undefined!\n");
       exit(EXIT_FAILURE);
     }
 
-  for ( lh = 0; lh < nhlev; lh++ )
+  double zp, ze;
+  double *halfpres = halfp;
+  for ( long lh = 0; lh < nhlev; lh++ )
     {
       zp = vct[lh];
       ze = vct[lh+nhlev+1];
 
-      for ( i = 0; i < ngp; i++ ) halfpres[i] = zp + ze * ps[i];
+      for ( long i = 0; i < ngp; i++ ) halfpres[i] = zp + ze * ps[i];
 
       halfpres += ngp;
     }
@@ -74,28 +69,25 @@ void presh(double * restrict fullp, double * halfp, const double *restrict vct,
   if ( fullp )
     {
       halfpres = halfp;
-      for ( i = 0; i < ngp*nhlev; i++ )
+      for ( long i = 0; i < ngp*nhlev; i++ )
 	fullp[i] = 0.5 * (halfpres[i] + halfpres[i+ngp]);
     }
 
 } /* presh */
 
 
-void genind(int *nx, const double * restrict plev, const double * restrict fullp, long ngp, long nplev, long nhlev)
+void genind(int *nx, const double *restrict plev, const double *restrict fullp, long ngp, long nplev, long nhlev)
 {
-  long  i, lp, lh;
-  int *nxl;
-  double pres;
-
   memset(nx, 0, ngp*nplev*sizeof(int));
 
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, lh, pres, nxl)
+#pragma omp parallel for default(none) shared(nx,plev,fullp,ngp,nplev,nhlev)
 #endif
-  for ( lp = 0; lp < nplev; lp++ )
+  for ( long lp = 0; lp < nplev; lp++ )
     {
-      pres = plev[lp];
-      nxl  = nx + lp*ngp;
+      long i, lh;
+      const double pres = plev[lp];
+      int *restrict nxl = nx + lp*ngp;
       for ( lh = 0; lh < nhlev; lh++ )
 	for ( i = 0; i < ngp ; i++ )
 	   {
@@ -106,21 +98,17 @@ void genind(int *nx, const double * restrict plev, const double * restrict fullp
 }  /* genind */
 
 
-void genindmiss(int *nx, const double * restrict plev, int ngp, int nplev, const double * restrict ps_prog, int * restrict pnmiss)
+void genindmiss(int *nx, const double *restrict plev, int ngp, int nplev, const double *restrict ps_prog, int *restrict pnmiss)
 {
-  long i, lp;
-  int *nxl;
-  double pres;
-
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, pres, nxl)
+#pragma omp parallel for default(none) shared(nx,plev,ngp,nplev,ps_prog,pnmiss)
 #endif
-  for ( lp = 0; lp < nplev; lp++ )
+  for ( long lp = 0; lp < nplev; lp++ )
     {
       pnmiss[lp] = 0;
-      pres = plev[lp];
-      nxl  = nx + lp*ngp;
-      for ( i = 0; i < ngp; i++ )
+      const double pres = plev[lp];
+      int *restrict nxl  = nx + lp*ngp;
+      for ( long i = 0; i < ngp; i++ )
 	{
 	  if ( pres > ps_prog[i] )
 	    {
@@ -133,17 +121,14 @@ void genindmiss(int *nx, const double * restrict plev, int ngp, int nplev, const
 }  /* genindmiss */
 
 
-void extra_P(double * restrict slp, const double * restrict halfp, const double * restrict fullp,
-	     const double * restrict geop, const double * restrict temp, long ngp)
+void extra_P(double *restrict slp, const double *restrict halfp, const double *restrict fullp,
+	     const double *restrict geop, const double *restrict temp, long ngp)
 {
   double alpha, tstar, tmsl, zprt, zprtal;
-  double zrg;
-  double zlapse = 0.0065;
-  long j;
+  const double zlapse = 0.0065;
+  const double zrg = 1.0 / PlanetGrav;
 
-  zrg = 1.0 / PlanetGrav;
-
-  for ( j = 0; j < ngp; ++j )
+  for ( long j = 0; j < ngp; ++j )
     {
       if ( geop[j] < 0.0001 && geop[j] > -0.0001 ) slp[j] = halfp[j];
       else
@@ -170,25 +155,22 @@ void extra_P(double * restrict slp, const double * restrict halfp, const double
 	  slp[j] = halfp[j] * exp(zprt*(1.0-zprtal*(0.5-zprtal/3.0)));
 	}
     }
-
 }  /* extrap */
 
 
 static 
 double extra_T(double pres, double halfp, double fullp, double geop, double temp)
 {
-  double tstar, ztsz, z1, ztmsl, zalph, peval, zhts, zalp;
-  double zrg;
-  double zlapse = 0.0065;
-
-  zrg   = 1.0 / PlanetGrav;
-  tstar = (1.0 + zlapse * PlanetRD * zrg * (halfp/fullp - 1.0)) * temp;
-  ztsz  = tstar;
-  z1    = tstar + zlapse * zrg * geop;
+  double peval;
+  const double zlapse = 0.0065;
+  const double zrg   = 1.0 / PlanetGrav;
+  double tstar = (1.0 + zlapse * PlanetRD * zrg * (halfp/fullp - 1.0)) * temp;
+  const double ztsz  = tstar;
+  const double z1    = tstar + zlapse * zrg * geop;
 
   if ( tstar < 255.0 ) tstar = 0.5 * (255.0 + tstar);
 
-  ztmsl = tstar + zlapse * zrg * geop;
+  double ztmsl = tstar + zlapse * zrg * geop;
 
   if ( ztmsl > 290.5 && tstar > 290.5 )
     {
@@ -202,9 +184,9 @@ double extra_T(double pres, double halfp, double fullp, double geop, double temp
     peval = ((halfp-pres)*temp+ (pres-fullp)*tstar)/ (halfp-fullp);
   else
     {
-      ztmsl = z1;
+      double ztmsl = z1;
       tstar = ztsz;
-      zhts  = geop * zrg;
+      const double zhts  = geop * zrg;
 
       if ( zhts > 2000. && z1 > 298. )
 	{
@@ -212,6 +194,7 @@ double extra_T(double pres, double halfp, double fullp, double geop, double temp
 	  if ( zhts < 2500. ) ztmsl = 0.002*((2500.-zhts)*z1+(zhts-2000.)*ztmsl);
 	}
 
+      double zalph;
       if ( (ztmsl-tstar) < 0.000001 )
 	zalph = 0.;
       else if (geop > 0.0001 || geop < -0.0001)
@@ -219,30 +202,26 @@ double extra_T(double pres, double halfp, double fullp, double geop, double temp
       else
 	zalph = PlanetRD*zlapse*zrg;
 
-      zalp  = zalph*log(pres/halfp);
+      double zalp  = zalph*log(pres/halfp);
       peval = tstar*(1.0+zalp*(1.0+zalp*(0.5+0.16666666667*zalp)));
     }
 
   return peval;
-
 }  /* extra_T */
 
 
 static 
 double extra_Z(double pres, double halfp, double fullp, double geop, double temp)
 {
-  double alpha, tstar, tmsl, zalp, zalpal;
-  double zrg;
-  double zlapse = 0.0065;
-  double ztlim = 290.5;
-
-  zrg   = 1.0 / PlanetGrav;
-  alpha = PlanetRD * zlapse * zrg;
-  tstar = (1.0 + alpha * (halfp/fullp - 1.0)) * temp;
+  const double zlapse = 0.0065;
+  const double ztlim = 290.5;
+  const double zrg   = 1.0 / PlanetGrav;
+  double alpha = PlanetRD * zlapse * zrg;
+  double tstar = (1.0 + alpha * (halfp/fullp - 1.0)) * temp;
 
   if ( tstar < 255.0 ) tstar = 0.5 * (255.0 + tstar);
 
-  tmsl = tstar + zlapse * zrg * geop;
+  double tmsl = tstar + zlapse * zrg * geop;
 
   if ( tmsl > ztlim && tstar > ztlim )
     {
@@ -257,28 +236,26 @@ double extra_Z(double pres, double halfp, double fullp, double geop, double temp
   else if ( geop > 0.0001 || geop < -0.0001 )
     alpha = PlanetRD * (tmsl-tstar) / geop;
 
-  zalp   = log(pres/halfp);
-  zalpal = zalp * alpha;
+  const double zalp   = log(pres/halfp);
+  const double zalpal = zalp * alpha;
 
-  return ((geop - PlanetRD*tstar*zalp*(1.0 + zalpal*(0.5 + zalpal/6.0)))*zrg);
+  return (geop - PlanetRD*tstar*zalp*(1.0 + zalpal*(0.5 + zalpal/6.0)))*zrg;
 }  /* extra_Z */
 
 
-void interp_X(const double * restrict gt, double *pt, const double * restrict hyb_press, const int *nx,
-	      const double * restrict plev, long nplev, long ngp, long nhlev, double missval)
+void interp_X(const double *restrict gt, double *pt, const double *restrict hyb_press, const int *nx,
+	      const double *restrict plev, long nplev, long ngp, long nhlev, double missval)
 {
-  long lp, i;
-  long nl, nh;
-
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, nl, nh)
+#pragma omp parallel for default(none) shared(gt,pt,hyb_press,nx,plev,nplev,ngp,nhlev,missval)
 #endif
-  for ( lp = 0; lp < nplev; lp++ )
+  for ( long lp = 0; lp < nplev; lp++ )
     {
-      double pres = plev[lp];
-      const int *nxl  = nx + lp*ngp;
-      double *ptl  = pt + lp*ngp;
-      for ( i = 0; i < ngp; i++ )
+      long nl, nh;
+      const double pres = plev[lp];
+      const int *restrict nxl  = nx + lp*ngp;
+      double *restrict ptl  = pt + lp*ngp;
+      for ( long i = 0; i < ngp; i++ )
 	{
 	  if ( nxl[i] == -1 )
 	    ptl[i] = missval;
@@ -298,25 +275,23 @@ void interp_X(const double * restrict gt, double *pt, const double * restrict hy
 }  /* interp_X */
 
 
-void interp_T(const double * restrict geop, const double * restrict gt, double *pt, const double * restrict fullp,
-	      const double * restrict halfp, const int *nx, const double * restrict plev, long nplev, long ngp,
+void interp_T(const double *restrict geop, const double *restrict gt, double *pt, const double *restrict fullp,
+	      const double *restrict halfp, const int *nx, const double *restrict plev, long nplev, long ngp,
 	      long nhlev, double missval)
 {
-  long lp, i;
-  long nl, nh;
-
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, nl, nh)
+#pragma omp parallel for default(none) shared(geop,gt,pt,fullp,halfp,nx,plev,nplev,ngp,nhlev,missval,Mars)
 #endif
-  for ( lp = 0; lp < nplev; lp++ )
+  for ( long lp = 0; lp < nplev; lp++ )
     {
-      double pres = plev[lp];
-      const int *nxl  = nx + lp*ngp;
-      double *ptl  = pt + lp*ngp;
+      long nl, nh;
+      const double pres = plev[lp];
+      const int *restrict nxl  = nx + lp*ngp;
+      double *restrict ptl  = pt + lp*ngp;
 #if defined(CRAY)
 #pragma _CRI inline extra_T
 #endif
-      for ( i = 0; i < ngp; i++ )
+      for ( long i = 0; i < ngp; i++ )
 	{
 	  nl = nxl[i];
 	  if ( nl < 0 )
@@ -348,13 +323,10 @@ void interp_T(const double * restrict geop, const double * restrict gt, double *
 }  /* interp_T */
 
 
-void interp_Z(const double * restrict geop, const double * restrict gz, double *pz, const double * restrict fullp,
-	      const double * restrict halfp, const int *nx, const double * restrict gt, const double * restrict plev,
+void interp_Z(const double *restrict geop, const double *restrict gz, double *pz, const double *restrict fullp,
+	      const double *restrict halfp, const int *nx, const double *restrict gt, const double *restrict plev,
 	      long nplev, long ngp, long nhlev, double missval)
 {
-  long lp, i;
-  long nl, nh;
-
   assert(geop != NULL);
   assert(gz != NULL);
   assert(pz != NULL);
@@ -362,17 +334,18 @@ void interp_Z(const double * restrict geop, const double * restrict gz, double *
   assert(halfp != NULL);
 
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, nl, nh)
+#pragma omp parallel for default(none) shared(geop,gz,pz,fullp,halfp,nx,gt,plev,nplev,ngp,nhlev,missval,Mars)
 #endif
-  for ( lp = 0; lp < nplev; lp++ )
+  for ( long lp = 0; lp < nplev; lp++ )
     {
-      double pres = plev[lp];
-      const int *nxl  = nx + lp*ngp;
-      double *pzl  = pz + lp*ngp;
+      long nl, nh;
+      const double pres = plev[lp];
+      const int *restrict nxl  = nx + lp*ngp;
+      double *restrict pzl  = pz + lp*ngp;
 #if defined(CRAY)
 #pragma _CRI inline extra_Z
 #endif
-      for ( i = 0; i < ngp; i++ )
+      for ( long i = 0; i < ngp; i++ )
 	{
 	  nl = nxl[i];
 	  if ( nl < 0 )
@@ -480,7 +453,7 @@ void vert_interp_lev3d(int gridsize, double missval, double *vardata1, double *v
  *
  * 3d version of vert_gen_weights() (src/Intlevel.c)
  */
-void vert_gen_weights3d(int expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
+void vert_gen_weights3d(bool expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
 			int *lev_idx1, int *lev_idx2, double *lev_wgt1, double *lev_wgt2)
 {
   int i,i1, i2;
@@ -572,7 +545,7 @@ void vert_gen_weights3d(int expol, int nlev1, int gridsize, double *lev1, int nl
  *
  * 3d1d version of vert_gen_weights() (src/Intlevel.c)
  */
-void vert_gen_weights3d1d(int expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
+void vert_gen_weights3d1d(bool expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
 			  int *lev_idx1, int *lev_idx2, double *lev_wgt1, double *lev_wgt2)
 {
   int i,i1, i2;
diff --git a/src/after_vertint.h b/src/after_vertint.h
index 8c315e7..4ddfbeb 100644
--- a/src/after_vertint.h
+++ b/src/after_vertint.h
@@ -1,6 +1,8 @@
 #ifndef _VINTERP_H
 #define _VINTERP_H
 
+#include <stdbool.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -28,9 +30,9 @@ void interp_X(const double * restrict gt, double *pt, const double * restrict hy
 
 void vert_interp_lev3d(int gridsize, double missval, double *vardata1, double *vardata2,
 		       int nlev2, int *lev_idx1, int *lev_idx2, double *lev_wgt1, double *lev_wgt2);
-void vert_gen_weights3d(int expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
+void vert_gen_weights3d(bool expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
 			int *lev_idx1, int *lev_idx2, double *lev_wgt1, double *lev_wgt2);
-void vert_gen_weights3d1d(int expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
+void vert_gen_weights3d1d(bool expol, int nlev1, int gridsize, double *lev1, int nlev2, double *lev2,
 			  int *lev_idx1, int *lev_idx2, double *lev_wgt1, double *lev_wgt2);
 
 #if defined(__cplusplus)
diff --git a/src/afterburnerlib.c b/src/afterburnerlib.c
index 19f1ba7..172dca5 100644
--- a/src/afterburnerlib.c
+++ b/src/afterburnerlib.c
@@ -36,7 +36,7 @@ char *FieldName(int code, const char *text)
 
   sprintf(name, "[%3d].%s", code, text);
 
-  return (name);
+  return name;
 }
 
 /* Free array space */
@@ -45,15 +45,13 @@ void *FreeMemory(void *ptr)
 {
   Free(ptr);
 
-  return (NULL);
+  return NULL;
 }
 
 static
 void FreeSpectral(struct Variable *vars)
 {
-  int code;
-
-  for ( code = MaxCodes-1; code >= 0; --code )
+  for ( int code = MaxCodes-1; code >= 0; --code )
     if ( vars[code].spectral )
       vars[code].spectral = (double *)FreeMemory(vars[code].spectral);
 }
@@ -61,9 +59,7 @@ void FreeSpectral(struct Variable *vars)
 static
 void FreeFourier(struct Variable *vars)
 {
-  int code;
-
-  for ( code = 0; code < MaxCodes; code++ )
+  for ( int code = 0; code < MaxCodes; code++ )
     if ( vars[code].fourier )
       vars[code].fourier = (double *)FreeMemory(vars[code].fourier);
 }
@@ -71,9 +67,7 @@ void FreeFourier(struct Variable *vars)
 static
 void FreeHybrid(struct Variable *vars)
 {
-  int code;
-
-  for ( code = 0; code < MaxCodes; code++ )
+  for ( int code = 0; code < MaxCodes; code++ )
     if ( vars[code].hybrid )
       vars[code].hybrid = (double *)FreeMemory(vars[code].hybrid);
 }
@@ -81,9 +75,7 @@ void FreeHybrid(struct Variable *vars)
 static
 void FreeGrid(struct Variable *vars)
 {
-  int code;
-
-  for ( code = 0; code < MaxCodes; code++ )
+  for ( int code = 0; code < MaxCodes; code++ )
     if ( vars[code].grid )
       vars[code].grid = (double *)FreeMemory(vars[code].grid);
 }
@@ -91,9 +83,7 @@ void FreeGrid(struct Variable *vars)
 static
 void FreeSamp(struct Variable *vars)
 {
-  int code;
-
-  for ( code = 0; code < MaxCodes; code++ )
+  for ( int code = 0; code < MaxCodes; code++ )
     if ( vars[code].samp )
       vars[code].samp = (int *)FreeMemory(vars[code].samp);
 }
@@ -111,7 +101,7 @@ double *alloc_dp(int words, const char *array_name)
       if ( result == NULL ) SysError(array_name, "No Memory!");
     }
 
-  return(result);
+  return result;
 }
 
 /* after_copy_array - Copy array of type double */
@@ -131,33 +121,26 @@ void after_zero_array(double *field, int words)
 static
 void IniQuaSum(double *dest, const double *restrict src, int len)
 {
-  int i;
-
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     dest[i] = src[i] * src[i];
 }
 
 static 
 void AddQuaSum(double *dest, const double *restrict src, int len)
 {
-  int i;
-
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     dest[i] += src[i] * src[i];
 }
 
 static
 void VarQuaSum(double *Variance, const double *restrict Sum, int len, int n)
 {
-  int i;
-  double rn1;
-
-  rn1 = 1.0 / (n-1);
+  const double rn1 = 1.0 / (n-1);
 
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     Variance[i] = (Variance[i] - Sum[i] * Sum[i] * n) * rn1;
 
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     if (Variance[i] > 0.0) Variance[i] = sqrt(Variance[i]);
     else                   Variance[i] = 0.0;
 }
@@ -165,11 +148,9 @@ void VarQuaSum(double *Variance, const double *restrict Sum, int len, int n)
 static
 void AddVector(double * restrict dest, const double *restrict src, long len, int *nmiss, double missval)
 {
-  long i;
-
   if ( *nmiss > 0 )
     {
-      for ( i = 0; i < len; i++ )
+      for ( long i = 0; i < len; i++ )
 	if ( IS_NOT_EQUAL(src[i], missval) )
 	  {
 	    if ( IS_NOT_EQUAL(dest[i], missval) )
@@ -179,7 +160,7 @@ void AddVector(double * restrict dest, const double *restrict src, long len, int
 	  }
 
       *nmiss = 0;
-      for ( i = 0; i < len; i++ )
+      for ( long i = 0; i < len; i++ )
 	if ( IS_EQUAL(dest[i], missval) ) *nmiss = *nmiss + 1;
 
       if ( *nmiss == 0 ) *nmiss = 1;
@@ -189,36 +170,30 @@ void AddVector(double * restrict dest, const double *restrict src, long len, int
 #if defined (_OPENMP)
 #pragma omp parallel for
 #endif
-      for ( i = 0; i < len; i++ ) dest[i] += src[i];
+      for ( long i = 0; i < len; i++ ) dest[i] += src[i];
     }
 }
 
 static
 void Add2Vectors(double *dest, const double *restrict srcA, const double *restrict srcB, int len)
 {
-  int i;
-
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     dest[i] = srcA[i] + srcB[i];
 }
 
 static
 void Sub2Vectors(double *dest, const double *restrict srcA, const double *restrict srcB, int len)
 {
-  int i;
-
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     dest[i] = srcA[i] - srcB[i];
 }
 
 static
 void MultVectorScalar(double *dest, const double *restrict src, double factor, int len, int nmiss, double missval)
 {
-  int i;
-
   if ( nmiss > 0 )
     {
-      for ( i = 0; i < len; i++ )
+      for ( int i = 0; i < len; i++ )
 	{
 	  if ( IS_EQUAL(src[i], missval) )
 	    dest[i] = missval;
@@ -228,18 +203,16 @@ void MultVectorScalar(double *dest, const double *restrict src, double factor, i
     }
   else
     {
-      for ( i = 0; i < len; i++ ) dest[i] = src[i] * factor;
+      for ( int i = 0; i < len; i++ ) dest[i] = src[i] * factor;
     }
 }
 
 static
 void DivVectorIvector(double *dest, const double *restrict src, const int *samp, int len, int *nmiss, double missval)
 {
-  int i;
-
   *nmiss = 0;
 
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     {
       if ( IS_EQUAL(src[i], missval) || samp[i] == 0 )
 	{
@@ -347,26 +320,24 @@ void sh2rh(int AnalysisData, double *sphum, double *rhum, double *t, int lev,
    int lp,i;
    int lpi,lfp;
    double  es, qsatr;
-   double *fullp;
-   double  RALPW, RBETW, RGAMW;
-   // double  RALPS, RBETS, RGAMS;
    double  RALP , RBET , RGAM ;
 
    /* ***************************************************** */
    /* Define constants for calculation in presence of water */
    /* ***************************************************** */
-   RGAMW = (C_RCW - C_RCPV) / C_RV;
-   RBETW = C_RLVTT / C_RV + RGAMW * C_RTT;
-   RALPW = log(C_RESTT) + RBETW / C_RTT + RGAMW * log(C_RTT);
+   const double RGAMW = (C_RCW - C_RCPV) / C_RV;
+   const double RBETW = C_RLVTT / C_RV + RGAMW * C_RTT;
+   const double RALPW = log(C_RESTT) + RBETW / C_RTT + RGAMW * log(C_RTT);
 
    /* ***************************************************** */
    /* Define constants for calculation in presence of  ice  */
    /* ***************************************************** */
    /*
-   RGAMS = (C_RCS - C_RCPV) / C_RV;
-   RBETS = C_RLSTT / C_RV + RGAMS * C_RTT;
-   RALPS = log(C_RESTT) + RBETS / C_RTT + RGAMS * log(C_RTT);
+   const double RGAMS = (C_RCS - C_RCPV) / C_RV;
+   const double RBETS = C_RLSTT / C_RV + RGAMS * C_RTT;
+   const double RALPS = log(C_RESTT) + RBETS / C_RTT + RGAMS * log(C_RTT);
    */
+   double *fullp;
    if (AnalysisData) fullp = level;
    else              fullp = fullpresshybrid;
 
@@ -401,23 +372,21 @@ void rh2sh(double *sphum, double *rhum, double *t, int lev, int dimgpout, double
    int lp,i;
    int lpi;
    double  es,qsat;
-   double  RALPW, RBETW, RGAMW;
-   // double  RALPS, RBETS, RGAMS;
    double  RALP , RBET , RGAM ;
 
 /* ***************************************************** */
 /* Define constants for calculation in presence of water */
 /* ***************************************************** */
-   RGAMW = (C_RCW - C_RCPV) / C_RV;
-   RBETW = C_RLVTT / C_RV + RGAMW * C_RTT;
-   RALPW = log(C_RESTT) + RBETW / C_RTT + RGAMW * log(C_RTT);
+   const double RGAMW = (C_RCW - C_RCPV) / C_RV;
+   const double RBETW = C_RLVTT / C_RV + RGAMW * C_RTT;
+   const double RALPW = log(C_RESTT) + RBETW / C_RTT + RGAMW * log(C_RTT);
 
 /* ***************************************************** */
 /* Define constants for calculation in presence of  ice  */
 /* ***************************************************** */
-   // RGAMS = (C_RCS - C_RCPV) / C_RV;
-   // RBETS = C_RLSTT / C_RV + RGAMS * C_RTT;
-   // RALPS = log(C_RESTT) + RBETS / C_RTT + RGAMS * log(C_RTT);
+   // const double RGAMS = (C_RCS - C_RCPV) / C_RV;
+   // const double RBETS = C_RLSTT / C_RV + RGAMS * C_RTT;
+   // const double RALPS = log(C_RESTT) + RBETS / C_RTT + RGAMS * log(C_RTT);
 
 /***************************************************/
 /* Diagnostics of saturation water vapour pressure */
@@ -444,7 +413,7 @@ void rh2sh(double *sphum, double *rhum, double *t, int lev, int dimgpout, double
 
 void after_FCrh2FCsh(struct Control *globs, struct Variable *vars)
 {
-   long fieldSize = globs->DimGP * globs->NumLevelRequest;
+   const long fieldSize = globs->DimGP * globs->NumLevelRequest;
 
    if ( vars[RHUMIDITY].grid == NULL )
      vars[RHUMIDITY].grid = alloc_dp(fieldSize, "vars[RHUMIDITY].grid");
@@ -472,13 +441,11 @@ void after_FCrh2FCsh(struct Control *globs, struct Variable *vars)
 
 void after_SPuv2SPdv(struct Control *globs, struct Variable *vars)
 {
-   int i;
-   long fieldSize;
    double *Div, *DivOut, *Vor, *VorOut;
 
    Div = DivOut = vars[DIVERGENCE].spectral;
    Vor = VorOut =  vars[VORTICITY].spectral;
-   fieldSize = globs->DimFC * globs->NumLevelRequest;
+   const long fieldSize = globs->DimFC * globs->NumLevelRequest;
 
    if ( vars[U_WIND].fourier == NULL )
      vars[U_WIND].fourier = alloc_dp(fieldSize, "vars[U_WIND].fourier");
@@ -495,22 +462,21 @@ void after_SPuv2SPdv(struct Control *globs, struct Variable *vars)
    vars[U_WIND].fourier = (double *)FreeMemory(vars[U_WIND].fourier);
    vars[V_WIND].fourier = (double *)FreeMemory(vars[V_WIND].fourier);
 
-   for (i = 0; i < globs->NumLevelRequest; ++i) {
-      sp2sp(Div, globs->Truncation, DivOut, globs->Truncation);
-      sp2sp(Vor, globs->Truncation, VorOut, globs->Truncation);
-      Div    += globs->DimSP;
-      Vor    += globs->DimSP;
-      DivOut += globs->DimSP;
-      VorOut += globs->DimSP;
-   }
+   for ( int i = 0; i < globs->NumLevelRequest; ++i )
+     {
+       sp2sp(Div, globs->Truncation, DivOut, globs->Truncation);
+       sp2sp(Vor, globs->Truncation, VorOut, globs->Truncation);
+       Div    += globs->DimSP;
+       Vor    += globs->DimSP;
+       DivOut += globs->DimSP;
+       VorOut += globs->DimSP;
+     }
 }
 
 
 void after_FCsh2FCrh(struct Control *globs, struct Variable *vars)
 {
-   long fieldSize;
-
-   fieldSize = globs->DimGP * globs->NumLevelRequest;
+   const long fieldSize = globs->DimGP * globs->NumLevelRequest;
 
    if ( vars[RHUMIDITY].grid == NULL )
      vars[RHUMIDITY].grid = alloc_dp(fieldSize, "vars[RHUMIDITY].grid");
@@ -958,36 +924,33 @@ static
 void theta(double *pthetaf, double *pthetah, double *ph, double *ps,
 	   double *tf, double *ts, int levels, int dimgp, int dim3gp)
 {
-   int h,l;
-   double  kappa;
    double *thetah = pthetah;
    double *thetaf = pthetaf;
 
-   kappa = PlanetRD / C_RCPD;
+   const double kappa = PlanetRD / C_RCPD;
 
-   for (h = 0; h < dimgp; h++) thetah[h] = 0.0;
+   for ( int h = 0; h < dimgp; h++ ) thetah[h] = 0.0;
    thetah += dimgp;
-   for (l = 0; l < levels - 1; l++) {
-      for (h = 0; h < dimgp; h++) {
+   for ( int l = 0; l < levels - 1; l++ )
+     {
+       for ( int h = 0; h < dimgp; h++ )
          thetah[h] = 0.5 * (tf[h] + tf[h+dimgp]) * pow((ps[h]/ph[h]),kappa);
-      }
-      ph += dimgp;
-      tf += dimgp;
-      thetah += dimgp;
-   }
+
+       ph += dimgp;
+       tf += dimgp;
+       thetah += dimgp;
+     }
+ 
    after_copy_array(thetah,ts,dimgp);
    thetah = pthetah;
-   for (h = 0; h < dim3gp; h++) {
-      thetaf[h] = 0.5 * (thetah[h] + thetah[h+dimgp]);
-   }
+   for ( int h = 0; h < dim3gp; h++ )
+     thetaf[h] = 0.5 * (thetah[h] + thetah[h+dimgp]);
 }
 
 static
 void windSpeed(double *uvspeed, double *u, double *v, int dim3gp)
 {
-  int i;
-
-  for (i = 0; i < dim3gp; i++)
+  for ( int i = 0; i < dim3gp; i++ )
     uvspeed[i] = sqrt(u[i] * u[i] + v[i] * v[i]);
 }
 
@@ -1572,66 +1535,6 @@ void after_EchamCompGP(struct Control *globs, struct Variable *vars)
 }
 
 static
-void CheckContent(struct Variable *vars, int timestep)
-{
-  for ( int code = 0; code < 272; code++ )
-    {
-      /*  if ( code == GEOPOTENTIAL ) continue; */
-      if ( code ==          SLP ) continue;
-      if ( code == GEOPOTHEIGHT ) continue;
-      if ( code ==       STREAM ) continue;
-      if ( code ==      VELOPOT ) continue;
-      if ( code ==       U_WIND ) continue;
-      if ( code ==       V_WIND ) continue;
-      if ( code ==        OMEGA ) continue;
-      if ( code ==    RHUMIDITY ) continue;
-      if ( code ==    LOW_CLOUD ) continue;
-      if ( code ==    MID_CLOUD ) continue;
-      if ( code ==    HIH_CLOUD ) continue;
-      if ( code ==           PS ) continue;
-      if ( code ==     HUMIDITY )
-	{
-	  if ( vars[code].needed && !vars[code].selected &&
-	       vars[code].spectral == NULL &&
-	       vars[code].hybrid   == NULL )
-	    {
-	      Warning( "No humidity in data file, set to zero !");
-	      vars[code].needed = FALSE;
-	    }
-	}
-      else
-	{
-	  if ( vars[code].needed && !vars[code].comp &&
-	       vars[code].spectral == NULL &&
-	       vars[code].hybrid   == NULL )
-	    {
-	      if ( labort_after )
-		Error( "Code  %3d not found at timestep %d!", code, timestep);
-	      else
-		Warning( "Code  %3d not found at timestep %d!", code, timestep);
-	    }
-	}
-    }
-  /*
-  if ( NumLevelRequest > 0 )
-    {
-      vars[HALF_PRESS].needed = 1;
-      vars[FULL_PRESS].needed = 1;
-    }
-
-  code = HALF_PRESS;
-  if ( vars[code].needed && !vars[code].comp &&
-       vars[code].spectral == NULL && vars[code].hybrid == NULL )
-    Error( "Hybrid model level not found!");
-
-  code = FULL_PRESS;
-  if ( vars[code].needed && !vars[code].comp &&
-       vars[code].spectral == NULL && vars[code].hybrid == NULL )
-    Error( "Hybrid model level not found!");
-  */
-}
-
-static
 void Derivate(double field[], double derilam[], int levels,
 	      int Waves, int Latitudes, double DerivationFactor[])
 {
@@ -1666,8 +1569,6 @@ void after_processML(struct Control *globs, struct Variable *vars)
   globs->MeanCount++;
   globs->TermCount++;
 
-  CheckContent(vars, globs->TermCount);
-
   if ( globs->MeanCount == 1 )
     {
       if ( globs->Debug ) Message( "TermCount = %d MeanCount = %d", globs->TermCount, globs->MeanCount);
@@ -2061,8 +1962,13 @@ void after_processML(struct Control *globs, struct Variable *vars)
 		  }
 		else
 		  {
-		    interp_X(vars[code].hybrid, vars[code].grid, vars[FULL_PRESS].hybrid,
-			     globs->vert_index, pressureLevel, globs->NumLevelRequest, globs->DimGP, globs->NumLevel, vars[code].missval);
+                    int numlevel = vars[code].hlev;
+                    if ( code == OMEGA ) numlevel = globs->NumLevel;
+                    double *hyb_press = vars[FULL_PRESS].hybrid;
+                    if ( numlevel == (globs->NumLevel+1) ) hyb_press = vars[HALF_PRESS].hybrid;
+
+		    interp_X(vars[code].hybrid, vars[code].grid, hyb_press,
+			     globs->vert_index, pressureLevel, globs->NumLevelRequest, globs->DimGP, numlevel, vars[code].missval);
 		  }
 
 		if ( ! globs->Extrapolate ) vars[code].nmiss = nmiss;
@@ -2614,7 +2520,7 @@ void after_EchamAddRecord(struct Control *globs, struct Variable *vars, int code
       vars[code].hlev = nlevel;
       vars[code].plev = nlevel;
       vars[code].sfit = FALSE;
-      if ( nlevel > 1 && leveltype == ZAXIS_HYBRID && nlevel == globs->NumLevel )
+      if ( nlevel > 1 && leveltype == ZAXIS_HYBRID && (nlevel == globs->NumLevel || nlevel == globs->NumLevel+1) )
 	{
 	  vars[code].plev = globs->NumLevelRequest;
 	  vars[code].sfit = TRUE;
diff --git a/src/cdo.c b/src/cdo.c
index 29a65a3..6fc669c 100644
--- a/src/cdo.c
+++ b/src/cdo.c
@@ -103,7 +103,7 @@ void gridsearch_set_method(const char *methodstr);
           } \
       }
 
-#define ISME  (strcmp(username, "\x6d\x32\x31\x34\x30\x30\x33") == 0)
+#define ITSME  (strcmp(username, "\x6d\x32\x31\x34\x30\x30\x33") == 0)
 
 static
 void cdo_stackframe(void)
@@ -203,11 +203,13 @@ void cdo_usage(void)
   fprintf(stderr, "    -b <nbits>     Set the number of bits for the output precision\n");
   fprintf(stderr, "                   (I8/I16/I32/F32/F64 for nc/nc2/nc4/nc4c; F32/F64 for grb2/srv/ext/ieg; P1 - P24 for grb/grb2)\n");
   fprintf(stderr, "                   Add L or B to set the byteorder to Little or Big endian\n");
-  if ( ISME )
+  if ( ITSME )
     {
       fprintf(stderr, "    --enableexcept <except>\n");
       fprintf(stderr, "                   Set individual floating-point traps (DIVBYZERO, INEXACT, INVALID, OVERFLOW, UNDERFLOW, ALL_EXCEPT)\n");
     }
+  fprintf(stderr, "    --cmor         CMOR conform NetCDF output\n");
+  fprintf(stderr, "    -C, --color    Colorized output messages\n");
   fprintf(stderr, "    -f, --format <format>\n");
   fprintf(stderr, "                   Format of the output file. (grb/grb2/nc/nc2/nc4/nc4c/srv/ext/ieg)\n");
   fprintf(stderr, "    -g <grid>      Set default grid name or file. Available grids: \n");
@@ -228,7 +230,7 @@ void cdo_usage(void)
   fprintf(stderr, "    -k <chunktype> NetCDF4 chunk type: auto, grid or lines\n");
   fprintf(stderr, "    -L             Lock IO (sequential access)\n");
   fprintf(stderr, "    -M             Switch to indicate that the I/O streams have missing values\n");
-  fprintf(stderr, "    -m <missval>   Set the default missing value (default: %g)\n", cdiInqMissval());
+  fprintf(stderr, "    -m <missval>   Set the missing value of non NetCDF files (default: %g)\n", cdiInqMissval());
   fprintf(stderr, "    --no_warnings  Inhibit warning messages\n");
   fprintf(stderr, "    -O             Overwrite existing output file, if checked\n");
   fprintf(stderr, "    --operators    List of all operators\n");
@@ -237,20 +239,22 @@ void cdo_usage(void)
 #endif
   fprintf(stderr, "    --percentile <method>\n");
   fprintf(stderr, "                   Percentile method: nrank, nist, numpy, numpy_lower, numpy_higher, numpy_nearest\n");
-  fprintf(stderr, "    -Q             Alphanumeric sorting of NetCDF parameter names\n");
   fprintf(stderr, "    --reduce_dim   Reduce NetCDF dimensions (module: TIMSTAT, FLDSTAT)\n");
   fprintf(stderr, "    -R, --regular  Convert GRIB1 data from reduced to regular grid (cgribex only)\n");
   fprintf(stderr, "    -r             Generate a relative time axis\n");
   fprintf(stderr, "    -S             Create an extra output stream for the module TIMSTAT. This stream\n");
   fprintf(stderr, "                   contains the number of non missing values for each output period.\n");
   fprintf(stderr, "    -s, --silent   Silent mode\n");
-  fprintf(stderr, "    -t <partab>    Set GRIB1 default parameter table name or file (cgribex only)\n");
+  fprintf(stderr, "    --sort         Alphanumeric sorting of NetCDF parameter names\n");
+  fprintf(stderr, "    -t <codetab>   Set GRIB1 default parameter code table name or file (cgribex only)\n");
   fprintf(stderr, "                   Predefined tables: ");
   for ( int id = 0; id < tableInqNumber(); id++ )
     if ( (name = tableInqNamePtr(id)) )
       fprintf(stderr, " %s", name);
   fprintf(stderr, "\n");
 
+  fprintf(stderr, "    --timestat_date <srcdate>\n");
+  fprintf(stderr, "                   Target timestamp (time statistics): first, middle, midhigh or last source timestep.\n");
   fprintf(stderr, "    -V, --version  Print the version number\n");
   fprintf(stderr, "    -v, --verbose  Print extra details for some operators\n");
   fprintf(stderr, "    -W             Print extra warning messages\n");
@@ -705,8 +709,6 @@ void defineVarnames(const char *arg)
 static
 void get_env_vars(void)
 {
-  char *envstr;
-
   username = getenv("LOGNAME");
   if ( username == NULL )
     {
@@ -714,7 +716,7 @@ void get_env_vars(void)
       if ( username == NULL ) username = "unknown";
     }
 
-  envstr = getenv("CDO_GRID_SEARCH_DIR");
+  char *envstr = getenv("CDO_GRID_SEARCH_DIR");
   if ( envstr )
     {
       size_t len = strlen(envstr);
@@ -846,7 +848,7 @@ void get_env_vars(void)
             fprintf(stderr, "CDO_COLOR = %s\n", envstr);
         }
     }
-  else if ( CDO_Color == FALSE && ISME ) CDO_Color = TRUE;
+  else if ( CDO_Color == FALSE && ITSME ) CDO_Color = TRUE;
 }
 
 static
@@ -986,15 +988,13 @@ void check_stacksize()
 #if defined(HAVE_GETRLIMIT)
 #if defined(RLIMIT_STACK)
   {
-#define  MIN_STACK_SIZE  67108864L  /* 64MB */
-    int status;
     struct rlimit rlim;
-    RLIM_T min_stack_size = MIN_STACK_SIZE;
-
-    status = getrlimit(RLIMIT_STACK, &rlim);
+    int status = getrlimit(RLIMIT_STACK, &rlim);
 
     if ( status == 0 )
       {
+#define  MIN_STACK_SIZE  67108864L  /* 64MB */
+        RLIM_T min_stack_size = MIN_STACK_SIZE;
         if ( min_stack_size > rlim.rlim_max ) min_stack_size = rlim.rlim_max;
         if ( rlim.rlim_cur < min_stack_size )
           {
@@ -1037,14 +1037,12 @@ static
 long str_to_int(const char *intstring)
 {
   long intval = -1;
-  long fact = 1;
 
   if ( intstring )
     {
-      int loop, len;
-
-      len = (int) strlen(intstring);
-      for ( loop = 0; loop < len; loop++ )
+      long fact = 1;
+      int len = (int) strlen(intstring);
+      for ( int loop = 0; loop < len; loop++ )
         {
           if ( ! isdigit((int) intstring[loop]) )
             {
@@ -1077,6 +1075,7 @@ int parse_options_long(int argc, char *argv[])
   int lpercentile;
   int lprintoperators = 0;
   int lenableexcept;
+  int ltimestat_date;
 
   struct cdo_option opt_long[] =
     {
@@ -1089,18 +1088,21 @@ int parse_options_long(int argc, char *argv[])
       { "gridsearchradius",  required_argument,  &lgridsearchradius,  1  },
       { "remap_genweights",  required_argument,  &lremap_genweights,  1  },
       { "enableexcept",      required_argument,      &lenableexcept,  1  },
+      { "timestat_date",     required_argument,     &ltimestat_date,  1  },
       { "cmor",                    no_argument,      &CDO_CMOR_Mode,  1  },
       { "reduce_dim",              no_argument,     &CDO_Reduce_Dim,  1  },
       { "float",                   no_argument,        &CDO_Memtype,  MEMTYPE_FLOAT  },
       { "rusage",                  no_argument,         &CDO_Rusage,  1  },
       { "operators",               no_argument,    &lprintoperators,  1  },
       { "no_warnings",             no_argument,           &_Verbose,  0  },
+      { "color",                   no_argument,                NULL, 'C' },
       { "format",            required_argument,                NULL, 'f' },
       { "help",                    no_argument,                NULL, 'h' },
       { "history",                 no_argument, &CDO_Append_History,  0  },
       { "no_history",              no_argument, &CDO_Append_History,  0  },
       { "regular",                 no_argument,                NULL, 'R' },
       { "silent",                  no_argument,                NULL, 's' },
+      { "sort",                    no_argument,                NULL, 'Q' },
       { "table",             required_argument,                NULL, 't' },
       { "verbose",                 no_argument,                NULL, 'v' },
       { "version",                 no_argument,                NULL, 'V' },
@@ -1118,6 +1120,7 @@ int parse_options_long(int argc, char *argv[])
       lgridsearchradius = 0;
       lremap_genweights = 0;
       lenableexcept = 0;
+      ltimestat_date = 0;
 
       c = cdo_getopt_long(argc, argv, "f:b:e:P:g:i:k:l:m:n:t:D:z:aBCcdhLMOpQRrsSTuVvWXZ", opt_long, NULL);
       if ( c == -1 ) break;
@@ -1157,6 +1160,17 @@ int parse_options_long(int argc, char *argv[])
               cdo_feenableexcept((unsigned)except);
               if ( signal(SIGFPE, cdo_sig_handler) == SIG_ERR ) cdoWarning("can't catch SIGFPE!");
             }
+          else if ( ltimestat_date )
+            {
+              int timestatdate = -1;
+              if      ( strcmp(CDO_optarg, "first")   == 0 ) timestatdate = TIMESTAT_FIRST;
+              else if ( strcmp(CDO_optarg, "last")    == 0 ) timestatdate = TIMESTAT_LAST;
+              else if ( strcmp(CDO_optarg, "middle")  == 0 ) timestatdate = TIMESTAT_MEAN;
+              else if ( strcmp(CDO_optarg, "midhigh") == 0 ) timestatdate = TIMESTAT_MIDHIGH;
+              if ( timestatdate < 0 ) cdoAbort("option --%s: unsupported argument: %s", "timestat_date", CDO_optarg);
+              extern int CDO_Timestat_Date;
+              CDO_Timestat_Date = timestatdate;
+            }
           else if ( luse_fftw )
             {
               int intarg = parameter2int(CDO_optarg);
@@ -1410,11 +1424,13 @@ int main(int argc, char *argv[])
       fprintf(stderr, "OMP num procs       = %d\n", omp_get_num_procs());
       fprintf(stderr, "OMP max threads     = %d\n", omp_get_max_threads());
       fprintf(stderr, "OMP num threads     = %d\n", omp_get_num_threads());
+#if defined(HAVE_OPENMP3)
       fprintf(stderr, "OMP thread limit    = %d\n", omp_get_thread_limit());
       omp_sched_t kind;
       int modifer;
       omp_get_schedule(&kind, &modifer);
       fprintf(stderr, "OMP schedule        = %d (1:static; 2:dynamic; 3:guided; 4:auto)\n", (int) kind);
+#endif
 #if defined(HAVE_OPENMP4)
       fprintf(stderr, "OMP proc bind       = %d (0:false; 1:true; 2:master; 3:close; 4:spread)\n", (int) omp_get_proc_bind());
 #if !defined(__ICC)
diff --git a/src/cdo_history.c b/src/cdo_history.c
index 3c41291..6eac85f 100644
--- a/src/cdo_history.c
+++ b/src/cdo_history.c
@@ -56,12 +56,14 @@ char *get_strtimeptr()
 
 void cdoInqHistory(int fileID)
 {
-  if ( ghistory )
+  if ( ghistory ) return;
+  /*
     {
       Free(ghistory);
       ghistorysize = 0;
       ghistory = NULL;
     }
+  */
 
   ghistorysize = streamInqHistorySize(fileID);
   if ( ghistorysize > 0 )
diff --git a/src/cdo_int.h b/src/cdo_int.h
index 94590c7..0eb1cbd 100644
--- a/src/cdo_int.h
+++ b/src/cdo_int.h
@@ -42,9 +42,22 @@
 #include "util.h"
 #include "datetime.h"
 
-#define  OPENMP4  201307
-#if defined(_OPENMP) && defined(OPENMP4) && _OPENMP >= OPENMP4
-#define  HAVE_OPENMP4  1
+#if defined(_OPENMP)
+#define  OPENMP3   200805 
+#define  OPENMP4   201307
+#define  OPENMP45  201511
+
+#if _OPENMP >= OPENMP3
+#define  HAVE_OPENMP3   1
+#endif
+
+#if _OPENMP >= OPENMP4
+#define  HAVE_OPENMP4   1
+#endif
+
+#if _OPENMP >= OPENMP45
+#define  HAVE_OPENMP45  1
+#endif
 #endif
 
 
@@ -79,11 +92,11 @@ enum T_EIGEN_MODE  {JACOBI, DANIELSON_LANCZOS};
 
 
 #ifndef  M_LN10
-#define  M_LN10      2.30258509299404568402  /* log_e 10 */
+#define  M_LN10      2.30258509299404568401799145468436421  /* log_e 10 */
 #endif
 
 #ifndef  M_PI
-#define  M_PI        3.14159265358979323846  /* pi */
+#define  M_PI        3.14159265358979323846264338327950288  /* pi */
 #endif
 
 
diff --git a/src/cdo_vlist.c b/src/cdo_vlist.c
index 42f13ae..471c72c 100644
--- a/src/cdo_vlist.c
+++ b/src/cdo_vlist.c
@@ -82,31 +82,35 @@ void compare_lon_reg2d(int xsize, int gridID1, int gridID2)
 static
 void compare_grid_unstructured(int gridID1, int gridID2)
 {
-  int gridsize = gridInqSize(gridID1);
-
-  double *xvals1 = (double*) Malloc(gridsize*sizeof(double));
-  double *xvals2 = (double*) Malloc(gridsize*sizeof(double));
-  double *yvals1 = (double*) Malloc(gridsize*sizeof(double));
-  double *yvals2 = (double*) Malloc(gridsize*sizeof(double));
-
-  gridInqXvals(gridID1, xvals1);
-  gridInqXvals(gridID2, xvals2);
-  gridInqYvals(gridID1, yvals1);
-  gridInqYvals(gridID2, yvals2);
-
-  int inc = gridsize > 10000 ? gridsize/1000 : 1;
-  for ( int i = 0; i < gridsize; i += inc )
-    if ( fabs(xvals1[i] - xvals2[i]) > 2.e-5 || fabs(yvals1[i] - yvals2[i]) > 2.e-5 )
-      {
-        // printf("%g %g %g %g %g %g\n", xvals1[i], xvals2[i], yvals1[i], yvals2[i], xvals1[i] - xvals2[i], yvals1[i] - yvals2[i]);
-	cdoWarning("Geographic location of some grid points differ!");
-	break;
-      }
+  if ( gridInqXvals(gridID1, NULL) == gridInqXvals(gridID2, NULL) &&
+       gridInqYvals(gridID1, NULL) == gridInqYvals(gridID2, NULL) )
+    {
+      int gridsize = gridInqSize(gridID1);
+      
+      double *xvals1 = (double*) Malloc(gridsize*sizeof(double));
+      double *xvals2 = (double*) Malloc(gridsize*sizeof(double));
+      double *yvals1 = (double*) Malloc(gridsize*sizeof(double));
+      double *yvals2 = (double*) Malloc(gridsize*sizeof(double));
+
+      gridInqXvals(gridID1, xvals1);
+      gridInqXvals(gridID2, xvals2);
+      gridInqYvals(gridID1, yvals1);
+      gridInqYvals(gridID2, yvals2);
+
+      int inc = gridsize > 10000 ? gridsize/1000 : 1;
+      for ( int i = 0; i < gridsize; i += inc )
+        if ( fabs(xvals1[i] - xvals2[i]) > 2.e-5 || fabs(yvals1[i] - yvals2[i]) > 2.e-5 )
+          {
+            // printf("%d %g %g %g %g %g %g\n", i, xvals1[i], xvals2[i], yvals1[i], yvals2[i], xvals1[i] - xvals2[i], yvals1[i] - yvals2[i]);
+            cdoWarning("Geographic location of some grid points differ!");
+            break;
+          }
       
-  Free(xvals1);
-  Free(xvals2);
-  Free(yvals1); 
-  Free(yvals2); 
+      Free(xvals1);
+      Free(xvals2);
+      Free(yvals1); 
+      Free(yvals2); 
+    }
 }
 
 static
@@ -367,3 +371,158 @@ int vlist_check_gridsize(int vlistID)
 
   return ngp;
 }
+
+
+double *vlist_read_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlev, int *rnhlevf, int *rnhlevh)
+{
+  int zaxisIDh = -1;
+  int nhlev = 0, nhlevf = 0, nhlevh = 0;
+  int nvct = 0;
+  double *vct = NULL;
+  
+  bool lhavevct = false;
+  int nzaxis = vlistNzaxis(vlistID);
+  for ( int i = 0; i < nzaxis; ++i )
+    {
+      // bool mono_level = false;
+      bool mono_level = true;
+      int zaxisID = vlistZaxis(vlistID, i);
+      int nlevel  = zaxisInqSize(zaxisID);
+
+      if ( (zaxisInqType(zaxisID) == ZAXIS_HYBRID || zaxisInqType(zaxisID) == ZAXIS_HYBRID_HALF) &&
+	   nlevel > 1 )
+	{
+	  int l;
+	  double *level = (double*) Malloc(nlevel*sizeof(double));
+	  zaxisInqLevels(zaxisID, level);
+	  for ( l = 0; l < nlevel; l++ )
+	    {
+	      if ( (l+1) != (int) (level[l]+0.5) ) break;
+	    }
+	  if ( l == nlevel ) mono_level = true; 
+	  Free(level);
+	}
+
+      if ( (zaxisInqType(zaxisID) == ZAXIS_HYBRID || zaxisInqType(zaxisID) == ZAXIS_HYBRID_HALF) &&
+	   nlevel > 1 && mono_level )
+	{
+	  nvct = zaxisInqVctSize(zaxisID);
+	  if ( nlevel == (nvct/2 - 1) )
+	    {
+	      if ( lhavevct == false )
+		{
+		  lhavevct = true;
+		  zaxisIDh = zaxisID;
+		  nhlev    = nlevel;
+		  nhlevf   = nhlev;
+		  nhlevh   = nhlevf + 1;
+	      
+		  vct = (double*) Malloc(nvct*sizeof(double));
+		  zaxisInqVct(zaxisID, vct);
+		}
+	    }
+	  else if ( nlevel == (nvct/2) )
+	    {
+	      if ( lhavevct == false )
+		{
+		  lhavevct = true;
+		  zaxisIDh = zaxisID;
+		  nhlev    = nlevel;
+		  nhlevf   = nhlev - 1;
+		  nhlevh   = nhlev;
+	      
+		  vct = (double*) Malloc(nvct*sizeof(double));
+		  zaxisInqVct(zaxisID, vct);
+		}
+	    }
+	  else if ( nlevel == (nvct - 4 - 1) )
+	    {
+	      if ( lhavevct == false )
+		{
+		  int vctsize;
+		  int voff = 4;
+
+		  double *rvct = (double*) Malloc(nvct*sizeof(double));
+		  zaxisInqVct(zaxisID,rvct);
+
+		  if ( (int)(rvct[0]+0.5) == 100000 && rvct[voff] < rvct[voff+1] )
+		    {
+		      lhavevct = true;
+		      zaxisIDh = zaxisID;
+		      nhlev    = nlevel;
+		      nhlevf   = nhlev;
+		      nhlevh   = nhlev + 1;
+
+		      vctsize = 2*nhlevh;
+		      vct = (double*) Malloc(vctsize*sizeof(double));
+
+		      /* calculate VCT for LM */
+
+		      for ( i = 0; i < vctsize/2; i++ )
+			{
+			  if ( rvct[voff+i] >= rvct[voff] && rvct[voff+i] <= rvct[3] )
+			    {
+			      vct[i] = rvct[0]*rvct[voff+i];
+			      vct[vctsize/2+i] = 0;
+			    }
+			  else
+			    {
+			      vct[i] = (rvct[0]*rvct[3]*(1-rvct[voff+i]))/(1-rvct[3]);
+			      vct[vctsize/2+i] = (rvct[voff+i]-rvct[3])/(1-rvct[3]);
+			    }
+			}
+		      
+		      if ( cdoVerbose )
+			{
+			  for ( i = 0; i < vctsize/2; i++ )
+			    fprintf(stdout, "%5d %25.17f %25.17f\n", i, vct[i], vct[vctsize/2+i]);
+			}
+		    }
+		  Free(rvct);
+		}
+	    }
+	}
+    }
+
+  *rzaxisIDh = zaxisIDh;
+  *rnvct   = nvct;
+  *rnhlev  = nhlev;
+  *rnhlevf = nhlevf;
+  *rnhlevh = nhlevh;
+  
+  return vct;
+}
+
+
+void vlist_change_hybrid_zaxis(int vlistID1, int vlistID2, int zaxisID1, int zaxisID2)
+{
+  int nvct0 = 0;
+  double *vct = NULL;
+
+  int nzaxis  = vlistNzaxis(vlistID1);
+  for ( int i = 0; i < nzaxis; ++i )
+    {
+      int zaxisID = vlistZaxis(vlistID1, i);
+      int nlevel  = zaxisInqSize(zaxisID);
+
+      if ( zaxisID == zaxisID1 && nlevel > 1 )
+	{
+	  int nvct = zaxisInqVctSize(zaxisID);
+          if ( vct == NULL )
+            {
+              nvct0 = nvct;
+              vct = (double*) Malloc(nvct*sizeof(double));
+              zaxisInqVct(zaxisID, vct);
+
+              vlistChangeZaxisIndex(vlistID2, i, zaxisID2);
+            }
+          else
+            {
+              if ( nvct0 == nvct && memcmp(vct, zaxisInqVctPtr(zaxisID), nvct*sizeof(double)) == 0 )
+                vlistChangeZaxisIndex(vlistID2, i, zaxisID2);
+	    }
+	}
+    }
+
+  if ( vct ) Free(vct);
+}
diff --git a/src/clipping/geometry.h b/src/clipping/geometry.h
index eb5011d..e8e4134 100644
--- a/src/clipping/geometry.h
+++ b/src/clipping/geometry.h
@@ -44,6 +44,10 @@
 #ifndef GEOMETRY_H
 #define GEOMETRY_H
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "grid.h"
 #include "utils.h"
 
@@ -140,7 +144,11 @@ int yac_point_in_cell2 (struct point point,  double point_coords[3],
  */
 static inline double get_angle (double a_lon, double b_lon) {
    double diff = a_lon - b_lon;
+#if defined(CDO)
+   return diff - lround(diff / (2.0 * M_PI)) * (2.0 * M_PI);
+#else
    return diff - round(diff / (2.0 * M_PI)) * (2.0 * M_PI);
+#endif
 }
 
 /** \example test_find_overlap.c
diff --git a/src/clipping/intersection.c b/src/clipping/intersection.c
index aefc75f..0c906a5 100644
--- a/src/clipping/intersection.c
+++ b/src/clipping/intersection.c
@@ -34,10 +34,6 @@
  * along with YAC.  If not, see <http://www.gnu.org/licenses/gpl.txt>.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <math.h>
 #include <stdio.h>
@@ -45,10 +41,6 @@
 #include "utils.h"
 #include "geometry.h"
 
-#if defined(CDO) && !defined(HAVE_SQRTL)
-#define sqrtl(x) (sqrt((double)x))
-#endif
-
 // angle tolerance
 const double yac_angle_tol = 1e-9;
 static double const tol = 1.0e-10;
@@ -226,9 +218,9 @@ static int vector_is_between_lat (double a[], double b[], double p[]) {
 
          // dot product is most accurate for angles around half PI
          // (for angles very close to half PI: alpha = fabs(acos(alpha))
-         double angle = fabs((double)(cross_cd[0] * a[0] +
+         double angle = fabs(cross_cd[0] * a[0] +
                              cross_cd[1] * a[1] +
-                             cross_cd[2] * a[2])) / length_cross_cd ;
+                             cross_cd[2] * a[2]) / length_cross_cd ;
 
          // if ab is on the plane of cd
          if (fabs(angle) < tol) {
@@ -258,9 +250,9 @@ static int vector_is_between_lat (double a[], double b[], double p[]) {
 
          // dot product is most accurate for angles around half PI
          // (for angles very close to half PI: alpha = fabs(acos(alpha))
-         double angle = fabs((double)(cross_ab[0] * c[0] +
+         double angle = fabs(cross_ab[0] * c[0] +
                              cross_ab[1] * c[1] +
-                             cross_ab[2] * c[2])) / length_cross_ab;
+                             cross_ab[2] * c[2]) / length_cross_ab;
 
          // if cd is on the plane of ab
          if (fabs(angle) < tol) {
@@ -447,9 +439,9 @@ int gcxgc_vec_ (double a[3], double b[3], double c[3], double d[3]) {
 
          // dot product is most accurate for angles around half PI
          // (for angles very close to half PI: alpha = fabs(acos(alpha))
-         double angle = fabs((double)(cross_cd[0] * a[0] +
+         double angle = fabs(cross_cd[0] * a[0] +
                              cross_cd[1] * a[1] +
-                             cross_cd[2] * a[2])) / length_cross_cd ;
+                             cross_cd[2] * a[2]) / length_cross_cd ;
 
          // if ab is not on the plane of cd
          if (fabs(angle) >= tol)
@@ -467,9 +459,9 @@ int gcxgc_vec_ (double a[3], double b[3], double c[3], double d[3]) {
 
          // dot product is most accurate for angles around half PI
          // (for angles very close to half PI: alpha = fabs(acos(alpha))
-         double angle = fabs((double)(cross_ab[0] * c[0] +
+         double angle = fabs(cross_ab[0] * c[0] +
                              cross_ab[1] * c[1] +
-                             cross_ab[2] * c[2])) / length_cross_ab;
+                             cross_ab[2] * c[2]) / length_cross_ab;
 
          // if cd is not on the plane of ab
          if (fabs(angle) >= tol)
diff --git a/src/commandline.c b/src/commandline.c
index 2d9d43b..49d8bce 100644
--- a/src/commandline.c
+++ b/src/commandline.c
@@ -15,63 +15,67 @@
   GNU General Public License for more details.
 */
 
+#include <stdio.h>
+#include <stdbool.h>
 #include <string.h>
+#include <stdlib.h>
+#include "dmemory.h"
 
 static int    gargc = 0;
 static char **gargv;
 
-static char CommandLine[1024];
+static char *CDO_CommandLine = NULL;
 
-void initCommandLine(void)
+
+void freeCommandLine(void)
 {
-  int iarg;
-  char *pargv;
-  size_t len, offset = 0;
-  /*
-  time_t tp;
-  struct tm *ltime;
+  if ( CDO_CommandLine ) Free(CDO_CommandLine);
+}
 
-  tp = time(NULL);
 
-  if ( tp != -1 )
-    {
-      ltime = localtime(&tp);
-      offset = strftime(CommandLine, 1024, "%d %b %Y : ", ltime);
-    }
-    */
-  for ( iarg = 0; iarg < gargc; iarg++ )
+void initCommandLine(void)
+{
+  size_t maxlen = 1;
+  for ( int iarg = 0; iarg < gargc; iarg++ ) maxlen += strlen(gargv[iarg]) + 1;
+
+  CDO_CommandLine = (char*) Malloc(maxlen);
+  atexit(freeCommandLine);
+  
+  char *pargv;
+  size_t offset = 0;
+  for ( int iarg = 0; iarg < gargc; iarg++ )
     {
       if ( iarg == 0 )
-	{
-	  pargv = strrchr(gargv[iarg], '/');
-	  if ( pargv == 0 ) pargv = gargv[0];
-	  else              pargv++;
-	}
+        {
+          pargv = strrchr(gargv[0], '/');
+          if ( pargv == 0 ) pargv = gargv[0];
+          else              pargv++;
+        }
       else
-	pargv = gargv[iarg];
-
-      len = strlen(pargv);
-      if ( offset+len+1 > 1024 ) break;
-      memcpy(CommandLine+offset, pargv, len);
+        pargv = gargv[iarg];
+      
+      size_t len = strlen(pargv);
+      if ( offset+len+1 > maxlen ) break;
+      memcpy(CDO_CommandLine+offset, pargv, len);
       offset += len;
-      CommandLine[offset] = ' ';
+      CDO_CommandLine[offset] = ' ';
       offset++;
     }
 
-  CommandLine[offset-1] = '\0';
+  CDO_CommandLine[offset-1] = '\0';
 }
 
 char *commandLine(void)
 {
-  static int init = 0;
+  static bool init = false;
 
-  if ( init == 0 )
+  if ( !init )
     {
       initCommandLine();
-      init = 1;
+      init = true;
     }
 
-  return (CommandLine);
+  return CDO_CommandLine;
 }
 
 void setCommandLine(int argc, char **argv)
diff --git a/src/config.h.in b/src/config.h.in
index 39c5388..25d540a 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -103,10 +103,10 @@
 /* Define to 1 if you have the `malloc' library (-lmalloc). */
 #undef HAVE_LIBMALLOC
 
-/* Define to 1 for NETCDF OpenDAP */
+/* Define to 1 for NetCDF OpenDAP */
 #undef HAVE_LIBNC_DAP
 
-/* Define to 1 for NETCDF support */
+/* Define to 1 for NetCDF support */
 #undef HAVE_LIBNETCDF
 
 /* Define to 1 for PROJ support */
@@ -133,9 +133,6 @@
 /* Define to 1 if you have the <libxml/tree.h> header file. */
 #undef HAVE_LIBXML_TREE_H
 
-/* Define 1 for ZLIB support */
-#undef HAVE_LIBZ
-
 /* Define to 1 if you have the <magics_api.h> header file. */
 #undef HAVE_MAGICS_API_H
 
@@ -151,16 +148,16 @@
 /* Define to 1 if you have a working `mmap' system call. */
 #undef HAVE_MMAP
 
-/* Define to 1 for NETCDF4/HDF5 support */
+/* Define to 1 for NetCDF4/HDF5 support */
 #undef HAVE_NC4HDF5
 
-/* Define to 1 for NETCDF4/HDF5 threadsafe support */
+/* Define to 1 for NetCDF4/HDF5 threadsafe support */
 #undef HAVE_NC4HDF5_THREADSAFE
 
-/* Define to 1 for NETCDF2 support */
+/* Define to 1 for NetCDF2 support */
 #undef HAVE_NETCDF2
 
-/* Define to 1 for NETCDF4 support */
+/* Define to 1 for NetCDF4 support */
 #undef HAVE_NETCDF4
 
 /* Define to 1 if you have the <netcdf.h> header file. */
@@ -223,9 +220,6 @@
 /* Define to 1 if you have the <wordexp.h> header file. */
 #undef HAVE_WORDEXP_H
 
-/* Define to 1 if you have the <zlib.h> header file. */
-#undef HAVE_ZLIB_H
-
 /* Host name */
 #undef HOST_NAME
 
diff --git a/src/datetime.c b/src/datetime.c
index 4043225..ff689bc 100644
--- a/src/datetime.c
+++ b/src/datetime.c
@@ -2,14 +2,12 @@
 #include "cdo_int.h"
 #include "datetime.h"
 
-static int timestat_date = -1;
+int CDO_Timestat_Date = -1;
 
 static
 void get_timestat_date(int *tstat_date)
 {
-  char *envstr;
-
-  envstr = getenv("CDO_TIMESTAT_DATE");
+  char *envstr = getenv("CDO_TIMESTAT_DATE");
   if ( envstr == NULL ) envstr = getenv("RUNSTAT_DATE");
   if ( envstr )
     {
@@ -20,9 +18,10 @@ void get_timestat_date(int *tstat_date)
       envstrl[7] = 0;
       strtolower(envstrl);
 
-      if      ( memcmp(envstrl, "first", 5)  == 0 )  env_date = TIMESTAT_FIRST;
-      else if ( memcmp(envstrl, "last", 4)   == 0 )  env_date = TIMESTAT_LAST;
-      else if ( memcmp(envstrl, "middle", 6) == 0 )  env_date = TIMESTAT_MEAN;
+      if      ( memcmp(envstrl, "first", 5)   == 0 )  env_date = TIMESTAT_FIRST;
+      else if ( memcmp(envstrl, "last", 4)    == 0 )  env_date = TIMESTAT_LAST;
+      else if ( memcmp(envstrl, "middle", 6)  == 0 )  env_date = TIMESTAT_MEAN;
+      else if ( memcmp(envstrl, "midhigh", 7) == 0 )  env_date = TIMESTAT_MIDHIGH;
 
       if ( env_date >= 0 )
 	{
@@ -38,15 +37,15 @@ void dtlist_init(dtlist_type *dtlist)
 {
   dtlist->nalloc     = 0;
   dtlist->size       = 0;
-  dtlist->calendar   = CALENDAR_STANDARD;
+  dtlist->calendar   = -1;
   dtlist->has_bounds = -1;
   dtlist->stat       = TIMESTAT_LAST;
   dtlist->dtinfo     = NULL;
 
-  if ( timestat_date == -1 )
+  if ( CDO_Timestat_Date == -1 )
     {
-      timestat_date = 0;
-      get_timestat_date(&timestat_date);
+      CDO_Timestat_Date = 0;
+      get_timestat_date(&CDO_Timestat_Date);
     }
 }
 
@@ -63,8 +62,7 @@ dtlist_type *dtlist_new(void)
 
 void dtlist_delete(dtlist_type *dtlist)
 {
-  if ( dtlist->nalloc > 0 && dtlist->dtinfo )
-    Free(dtlist->dtinfo);
+  if ( dtlist->nalloc > 0 && dtlist->dtinfo ) Free(dtlist->dtinfo);
 
   Free(dtlist);
 }
@@ -85,16 +83,53 @@ void dtlist_taxisInqTimestep(dtlist_type *dtlist, int taxisID, int tsID)
   dtlist->dtinfo[tsID].v.date = taxisInqVdate(taxisID);
   dtlist->dtinfo[tsID].v.time = taxisInqVtime(taxisID);
 
-  if ( tsID == 0 && dtlist->has_bounds == -1 )
+  dtlist->dtinfo[tsID].c.date = dtlist->dtinfo[tsID].v.date;
+  dtlist->dtinfo[tsID].c.time = dtlist->dtinfo[tsID].v.time;
+
+  if ( tsID == 0 )
     {
-      dtlist->has_bounds = 0;
-      if ( taxisHasBounds(taxisID) ) dtlist->has_bounds = 1;
+      if ( dtlist->has_bounds == -1 )
+        {
+          dtlist->has_bounds = 0;
+          if ( taxisHasBounds(taxisID) ) dtlist->has_bounds = 1;
+        }
+
+      if ( dtlist->calendar == -1 )
+        {
+          dtlist->calendar = taxisInqCalendar(taxisID);
+        }
     }
 
   if ( dtlist->has_bounds )
     {
       taxisInqVdateBounds(taxisID, &(dtlist->dtinfo[tsID].b[0].date), &(dtlist->dtinfo[tsID].b[1].date));
       taxisInqVtimeBounds(taxisID, &(dtlist->dtinfo[tsID].b[0].time), &(dtlist->dtinfo[tsID].b[1].time));
+
+      if ( dtlist->dtinfo[tsID].v.date == dtlist->dtinfo[tsID].b[1].date &&
+           dtlist->dtinfo[tsID].v.time == dtlist->dtinfo[tsID].b[1].time )
+        {
+          int calendar = dtlist->calendar;
+          
+          int vdate = dtlist->dtinfo[tsID].b[0].date;
+          int vtime = dtlist->dtinfo[tsID].b[0].time;
+          juldate_t juldate1 = juldate_encode(calendar, vdate, vtime);
+          
+          vdate = dtlist->dtinfo[tsID].b[1].date;
+          vtime = dtlist->dtinfo[tsID].b[1].time;
+          juldate_t juldate2 = juldate_encode(calendar, vdate, vtime);
+
+          // int hour, minute, second;
+          // cdiDecodeTime(vtime, &hour, &minute, &second);
+          
+          if ( vtime == 0 && juldate_to_seconds(juldate1) < juldate_to_seconds(juldate2) )
+            {
+              juldate_t juldate = juldate_add_seconds(-1, juldate2);
+              juldate_decode(calendar, juldate, &vdate, &vtime);
+
+              dtlist->dtinfo[tsID].c.date = vdate;
+              dtlist->dtinfo[tsID].c.time = vtime;
+            }
+        }
     }
   else
     {
@@ -129,6 +164,26 @@ void dtlist_mean(dtlist_type *dtlist, int nsteps)
     {
       int calendar = dtlist->calendar;
 
+//#define TEST_DTLIST_MEAN 1
+#ifdef TEST_DTLIST_MEAN
+      vdate = dtlist->dtinfo[0].v.date;
+      vtime = dtlist->dtinfo[0].v.time;
+      juldate_t juldate0 = juldate_encode(calendar, vdate, vtime);
+
+      juldate_t juldate;
+      double seconds = 0;
+      for ( int i = 1; i < nsteps; ++i )
+        {
+          vdate = dtlist->dtinfo[i].v.date;
+          vtime = dtlist->dtinfo[i].v.time;
+          juldate = juldate_encode(calendar, vdate, vtime);
+
+          seconds += juldate_to_seconds(juldate_sub(juldate, juldate0));
+        }
+      
+      juldate = juldate_add_seconds((int)lround(seconds/nsteps), juldate0);
+      juldate_decode(calendar, juldate, &vdate, &vtime);
+#else
       vdate = dtlist->dtinfo[nsteps/2-1].v.date;
       vtime = dtlist->dtinfo[nsteps/2-1].v.time;
       juldate_t juldate1 = juldate_encode(calendar, vdate, vtime);
@@ -140,6 +195,7 @@ void dtlist_mean(dtlist_type *dtlist, int nsteps)
       double seconds = juldate_to_seconds(juldate_sub(juldate2, juldate1)) / 2;
       juldate_t juldatem = juldate_add_seconds((int)lround(seconds), juldate1);
       juldate_decode(calendar, juldatem, &vdate, &vtime);
+#endif
     }
   else
     {
@@ -152,17 +208,29 @@ void dtlist_mean(dtlist_type *dtlist, int nsteps)
 }
 
 
+void dtlist_midhigh(dtlist_type *dtlist, int nsteps)
+{
+  int vdate = dtlist->dtinfo[nsteps/2].v.date;
+  int vtime = dtlist->dtinfo[nsteps/2].v.time;
+
+  dtlist->timestat.v.date = vdate;
+  dtlist->timestat.v.time = vtime;
+}
+
+
 void dtlist_stat_taxisDefTimestep(dtlist_type *dtlist, int taxisID, int nsteps)
 {
   if ( (size_t)nsteps > dtlist->size )
     cdoAbort("Internal error; unexpected nsteps=%d (limit=%ld)!", nsteps, dtlist->size);
 
   int stat = dtlist->stat;
-  if ( timestat_date > 0 ) stat = timestat_date;
+  if ( CDO_Timestat_Date > 0 ) stat = CDO_Timestat_Date;
 
-  if      ( stat == TIMESTAT_MEAN  ) dtlist_mean(dtlist, nsteps);
-  else if ( stat == TIMESTAT_FIRST ) dtlist->timestat.v = dtlist->dtinfo[0].v;
-  else if ( stat == TIMESTAT_LAST  ) dtlist->timestat.v = dtlist->dtinfo[nsteps-1].v;
+  if      ( stat == TIMESTAT_MEAN    ) dtlist_mean(dtlist, nsteps);
+  else if ( stat == TIMESTAT_MIDHIGH ) dtlist_midhigh(dtlist, nsteps);
+  else if ( stat == TIMESTAT_FIRST   ) dtlist->timestat.v = dtlist->dtinfo[0].v;
+  else if ( stat == TIMESTAT_LAST    ) dtlist->timestat.v = dtlist->dtinfo[nsteps-1].v;
+  else cdoAbort("Internal error; implementation missing for timestat=%d", stat);
 
   if ( dtlist->has_bounds )
     {
@@ -211,7 +279,7 @@ int dtlist_get_vdate(dtlist_type *dtlist, int tsID)
   if ( tsID < 0 || (size_t)tsID >= dtlist->size )
     cdoAbort("Internal error; tsID out of bounds!");
 
-  return dtlist->dtinfo[tsID].v.date;
+  return dtlist->dtinfo[tsID].c.date;
 }
 
 
@@ -220,28 +288,26 @@ int dtlist_get_vtime(dtlist_type *dtlist, int tsID)
   if ( tsID < 0 || (size_t)tsID >= dtlist->size )
     cdoAbort("Internal error; tsID out of bounds!");
 
-  return dtlist->dtinfo[tsID].v.time;
+  return dtlist->dtinfo[tsID].c.time;
 }
 
 
-void datetime_avg(int calendar, int ndates, datetime_t *datetime)
+void datetime_avg(int calendar, int ndates, cdo_datetime_t *datetime)
 {
   int vdate, vtime;
-  juldate_t juldate1, juldate2, juldatem;
-  double seconds;
 
   if ( ndates%2 == 0 )
     {
       vdate = datetime[ndates/2-1].date;
       vtime = datetime[ndates/2-1].time;
-      juldate1 = juldate_encode(calendar, vdate, vtime);
+      juldate_t juldate1 = juldate_encode(calendar, vdate, vtime);
 
       vdate = datetime[ndates/2].date;
       vtime = datetime[ndates/2].time;
-      juldate2 = juldate_encode(calendar, vdate, vtime);
+      juldate_t juldate2 = juldate_encode(calendar, vdate, vtime);
 
-      seconds = juldate_to_seconds(juldate_sub(juldate2, juldate1)) / 2;
-      juldatem = juldate_add_seconds((int)lround(seconds), juldate1);
+      double seconds = juldate_to_seconds(juldate_sub(juldate2, juldate1)) / 2;
+      juldate_t juldatem = juldate_add_seconds((int)lround(seconds), juldate1);
       juldate_decode(calendar, juldatem, &vdate, &vtime);
     }
   else
diff --git a/src/datetime.h b/src/datetime.h
index 18b5caa..2b98258 100644
--- a/src/datetime.h
+++ b/src/datetime.h
@@ -3,9 +3,10 @@
 
 #include <stdio.h>
 
-#define  TIMESTAT_FIRST  1
-#define  TIMESTAT_LAST   2
-#define  TIMESTAT_MEAN   3
+#define  TIMESTAT_FIRST    1
+#define  TIMESTAT_LAST     2
+#define  TIMESTAT_MEAN     3
+#define  TIMESTAT_MIDHIGH  4
 
 
 typedef struct {
@@ -17,18 +18,13 @@ typedef struct {
 typedef struct {
   int   date;
   int   time;
-} datetime_t;
-
-
-typedef struct {
-  int   date;
-  int   time;
-} datetime_type;
+} cdo_datetime_t;
 
 typedef struct
 {
-  datetime_type v;
-  datetime_type b[2];
+  cdo_datetime_t c;     // corrected verification time
+  cdo_datetime_t v;     // verification time
+  cdo_datetime_t b[2];  // time bounds
 } dtinfo_type;
 
 typedef struct
@@ -52,7 +48,7 @@ juldate_t juldate_add_seconds(int seconds, juldate_t juldate);
 double    juldate_to_seconds(juldate_t juldate);
 
 
-void    datetime_avg(int dpy, int ndates, datetime_t *datetime);
+void    datetime_avg(int dpy, int ndates, cdo_datetime_t *datetime);
 
 dtlist_type *dtlist_new(void);
 void dtlist_delete(dtlist_type *dtlist);
diff --git a/src/exception.c b/src/exception.c
index 1197283..e92b79e 100644
--- a/src/exception.c
+++ b/src/exception.c
@@ -67,20 +67,18 @@ void cdiOpenError(int cdiErrno, const char *fmt, const char *path)
 
 void cdoAbort(const char *fmt, ...)
 {
-  va_list args;
-	
-  va_start(args, fmt);
-
   printf("\n");
   set_text_color(stderr, RESET, RED);
    fprintf(stderr, "%s (Abort): ", processInqPrompt());
   reset_text_color(stderr);
+  
   set_text_color(stderr, RESET, BLACK);
+  va_list args;	
+  va_start(args, fmt);
   vfprintf(stderr, fmt, args);
-  reset_text_color(stderr);
-   fprintf(stderr, "\n");
-
   va_end(args);
+  reset_text_color(stderr);
+  fprintf(stderr, "\n");
 
   if ( _ExitOnError ) pstreamCloseAll();
   if ( _ExitOnError ) exit(EXIT_FAILURE);
@@ -91,39 +89,73 @@ void cdoWarning(const char *fmt, ...)
 {
   if ( _Verbose )
     {
-      va_list args;
-
-      va_start(args, fmt);
-
       set_text_color(stderr, BRIGHT, YELLOW);
       fprintf(stderr, "%s (Warning): ", processInqPrompt());
       reset_text_color(stderr);
+
       set_text_color(stderr, RESET, BLACK);
+      va_list args;
+      va_start(args, fmt);
       vfprintf(stderr, fmt, args);
+      va_end(args);
       reset_text_color(stderr);
       fprintf(stderr, "\n");
-
-      va_end(args);
     }
 }
 
 
 void cdoPrint(const char *fmt, ...)
 {
-  va_list args;
-
   if ( ! cdoSilentMode )
     {
+      set_text_color(stderr, RESET, GREEN);
+      fprintf(stderr, "%s: ", processInqPrompt());
+      reset_text_color(stderr);
+
+      set_text_color(stderr, RESET, BLACK);
+      va_list args;
       va_start(args, fmt);
+      vfprintf(stderr, fmt, args);
+      va_end(args);
+      reset_text_color(stderr);
+      fprintf(stderr, "\n");
+    }
+}
+
 
+void cdoPrintBlue(const char *fmt, ...)
+{
+  if ( ! cdoSilentMode )
+    {
       set_text_color(stderr, RESET, GREEN);
       fprintf(stderr, "%s: ", processInqPrompt());
       reset_text_color(stderr);
-      set_text_color(stderr, RESET, BLACK);
+
+      set_text_color(stderr, RESET, BLUE);
+      va_list args;
+      va_start(args, fmt);
       vfprintf(stderr, fmt, args);
+      va_end(args);
       reset_text_color(stderr);
       fprintf(stderr, "\n");
+    }
+}
 
+
+void cdoPrintRed(const char *fmt, ...)
+{
+  if ( ! cdoSilentMode )
+    {
+      set_text_color(stderr, RESET, GREEN);
+      fprintf(stderr, "%s: ", processInqPrompt());
+      reset_text_color(stderr);
+
+      set_text_color(stderr, RESET, RED);
+      va_list args;
+      va_start(args, fmt);
+      vfprintf(stderr, fmt, args);
       va_end(args);
+      reset_text_color(stderr);
+      fprintf(stderr, "\n");
     }
 }
diff --git a/src/expr.c b/src/expr.c
index bea9b41..bf056a0 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -59,7 +59,7 @@ enum {FT_STD, FT_CONST, FT_FLD, FT_VERT, FT_COORD, FT_1C};
 #define  MVCOMPOR(x,y)  (DBL_IS_EQUAL((x),missval1) ? missval1 : COMPOR(x,y))
 
 static double f_int(double x)          { return (int)(x); }
-static double f_nint(double x)         { return round(x); }
+static double f_nint(double x)         { return (double)lround(x); }
 static double f_sqr(double x)          { return x*x;      }
 static double f_rad(double x)          { return x*M_PI/180.; }
 static double f_deg(double x)          { return x*180./M_PI; }
@@ -72,67 +72,68 @@ typedef struct {
   int type;
   int flag;
   const char *name;  // function name
-  void (*func)();    // pointer to function
+  double (*func)();    // pointer to function
 }
 func_t;
 
 static func_t fun_sym_tbl[] =
 {
   // scalar functions
-  {FT_STD, 0, "abs",   (void (*)()) fabs},
-  {FT_STD, 0, "floor", (void (*)()) floor},
-  {FT_STD, 0, "ceil",  (void (*)()) ceil},
-  {FT_STD, 0, "int",   (void (*)()) f_int},
-  {FT_STD, 0, "nint",  (void (*)()) f_nint},
-  {FT_STD, 0, "sqr",   (void (*)()) f_sqr},
-  {FT_STD, 0, "sqrt",  (void (*)()) sqrt},
-  {FT_STD, 0, "exp",   (void (*)()) exp},
-  {FT_STD, 0, "erf",   (void (*)()) erf},
-  {FT_STD, 0, "log",   (void (*)()) log},
-  {FT_STD, 0, "log10", (void (*)()) log10},
-  {FT_STD, 0, "sin",   (void (*)()) sin},
-  {FT_STD, 0, "cos",   (void (*)()) cos},
-  {FT_STD, 0, "tan",   (void (*)()) tan},
-  {FT_STD, 0, "sinh",  (void (*)()) sinh},
-  {FT_STD, 0, "cosh",  (void (*)()) cosh},
-  {FT_STD, 0, "tanh",  (void (*)()) tanh},
-  {FT_STD, 0, "asin",  (void (*)()) asin},
-  {FT_STD, 0, "acos",  (void (*)()) acos},
-  {FT_STD, 0, "atan",  (void (*)()) atan},
-  {FT_STD, 0, "asinh", (void (*)()) asinh},
-  {FT_STD, 0, "acosh", (void (*)()) acosh},
-  {FT_STD, 0, "atanh", (void (*)()) atanh},
-  {FT_STD, 0, "gamma", (void (*)()) tgamma},
-  {FT_STD, 0, "rad",   (void (*)()) f_rad},
-  {FT_STD, 0, "deg",   (void (*)()) f_deg},
+  {FT_STD, 0, "abs",   (double (*)()) (double (*)(double)) fabs},
+  {FT_STD, 0, "floor", (double (*)()) (double (*)(double)) floor},
+  {FT_STD, 0, "ceil",  (double (*)()) (double (*)(double)) ceil},
+  {FT_STD, 0, "sqrt",  (double (*)()) (double (*)(double)) sqrt},
+  {FT_STD, 0, "exp",   (double (*)()) (double (*)(double)) exp},
+  {FT_STD, 0, "erf",   (double (*)()) (double (*)(double)) erf},
+  {FT_STD, 0, "log",   (double (*)()) (double (*)(double)) log},
+  {FT_STD, 0, "ln",    (double (*)()) (double (*)(double)) log},
+  {FT_STD, 0, "log10", (double (*)()) (double (*)(double)) log10},
+  {FT_STD, 0, "sin",   (double (*)()) (double (*)(double)) sin},
+  {FT_STD, 0, "cos",   (double (*)()) (double (*)(double)) cos},
+  {FT_STD, 0, "tan",   (double (*)()) (double (*)(double)) tan},
+  {FT_STD, 0, "sinh",  (double (*)()) (double (*)(double)) sinh},
+  {FT_STD, 0, "cosh",  (double (*)()) (double (*)(double)) cosh},
+  {FT_STD, 0, "tanh",  (double (*)()) (double (*)(double)) tanh},
+  {FT_STD, 0, "asin",  (double (*)()) (double (*)(double)) asin},
+  {FT_STD, 0, "acos",  (double (*)()) (double (*)(double)) acos},
+  {FT_STD, 0, "atan",  (double (*)()) (double (*)(double)) atan},
+  {FT_STD, 0, "asinh", (double (*)()) (double (*)(double)) asinh},
+  {FT_STD, 0, "acosh", (double (*)()) (double (*)(double)) acosh},
+  {FT_STD, 0, "atanh", (double (*)()) (double (*)(double)) atanh},
+  {FT_STD, 0, "gamma", (double (*)()) (double (*)(double)) tgamma},
+  {FT_STD, 0, "int",   (double (*)()) f_int},
+  {FT_STD, 0, "nint",  (double (*)()) f_nint},
+  {FT_STD, 0, "sqr",   (double (*)()) f_sqr},
+  {FT_STD, 0, "rad",   (double (*)()) f_rad},
+  {FT_STD, 0, "deg",   (double (*)()) f_deg},
 
   // constant functions
-  {FT_CONST, 0, "ngp",     (void (*)()) pt_ngp},      // number of horizontal grid points
-  {FT_CONST, 0, "nlev",    (void (*)()) pt_nlev},     // number of vertical levels
-  {FT_CONST, 0, "size",    (void (*)()) pt_size},     // ngp*nlev
-  {FT_CONST, 0, "missval", (void (*)()) pt_missval},  // Returns the missing value of a variable
+  {FT_CONST, 0, "ngp",     (double (*)()) pt_ngp},      // number of horizontal grid points
+  {FT_CONST, 0, "nlev",    (double (*)()) pt_nlev},     // number of vertical levels
+  {FT_CONST, 0, "size",    (double (*)()) pt_size},     // ngp*nlev
+  {FT_CONST, 0, "missval", (double (*)()) pt_missval},  // Returns the missing value of a variable
 
   // cdo field functions (Reduce grid to point)
-  {FT_FLD, 0, "fldmin",  (void (*)()) fldmin},
-  {FT_FLD, 0, "fldmax",  (void (*)()) fldmax},
-  {FT_FLD, 0, "fldsum",  (void (*)()) fldsum},
-  {FT_FLD, 1, "fldmean", (void (*)()) fldmean},
-  {FT_FLD, 1, "fldavg",  (void (*)()) fldavg},
-  {FT_FLD, 1, "fldstd",  (void (*)()) fldstd},
-  {FT_FLD, 1, "fldstd1", (void (*)()) fldstd1},
-  {FT_FLD, 1, "fldvar",  (void (*)()) fldvar},
-  {FT_FLD, 1, "fldvar1", (void (*)()) fldvar1},
+  {FT_FLD, 0, "fldmin",  (double (*)()) fldmin},
+  {FT_FLD, 0, "fldmax",  (double (*)()) fldmax},
+  {FT_FLD, 0, "fldsum",  (double (*)()) fldsum},
+  {FT_FLD, 1, "fldmean", (double (*)()) fldmean},
+  {FT_FLD, 1, "fldavg",  (double (*)()) fldavg},
+  {FT_FLD, 1, "fldstd",  (double (*)()) fldstd},
+  {FT_FLD, 1, "fldstd1", (double (*)()) fldstd1},
+  {FT_FLD, 1, "fldvar",  (double (*)()) fldvar},
+  {FT_FLD, 1, "fldvar1", (double (*)()) fldvar1},
 
   // cdo field functions (Reduce level to point)
-  {FT_VERT, 0, "vertmin",  (void (*)()) fldmin},
-  {FT_VERT, 0, "vertmax",  (void (*)()) fldmax},
-  {FT_VERT, 0, "vertsum",  (void (*)()) fldsum},
-  {FT_VERT, 1, "vertmean", (void (*)()) fldmean},
-  {FT_VERT, 1, "vertavg",  (void (*)()) fldavg},
-  {FT_VERT, 1, "vertstd",  (void (*)()) fldstd},
-  {FT_VERT, 1, "vertstd1", (void (*)()) fldstd1},
-  {FT_VERT, 1, "vertvar",  (void (*)()) fldvar},
-  {FT_VERT, 1, "vertvar1", (void (*)()) fldvar1},
+  {FT_VERT, 0, "vertmin",  (double (*)()) fldmin},
+  {FT_VERT, 0, "vertmax",  (double (*)()) fldmax},
+  {FT_VERT, 0, "vertsum",  (double (*)()) fldsum},
+  {FT_VERT, 1, "vertmean", (double (*)()) fldmean},
+  {FT_VERT, 1, "vertavg",  (double (*)()) fldavg},
+  {FT_VERT, 1, "vertstd",  (double (*)()) fldstd},
+  {FT_VERT, 1, "vertstd1", (double (*)()) fldstd1},
+  {FT_VERT, 1, "vertvar",  (double (*)()) fldvar},
+  {FT_VERT, 1, "vertvar1", (double (*)()) fldvar1},
   
   {FT_COORD, 0, "clon",       NULL},
   {FT_COORD, 0, "clat",       NULL},
@@ -953,7 +954,7 @@ nodeType *fun1c(int init, int funcID, nodeType *p1, double value, parse_param_t
     {
       parse_arg->coords[coordID].needed = true;
 
-      data = (double*) malloc(nlev*sizeof(double));
+      data = (double*) Malloc(nlev*sizeof(double));
       zaxisInqLevels(zaxisID, data);
     }
   else
diff --git a/src/features.c b/src/features.c
index 120a601..a57b899 100644
--- a/src/features.c
+++ b/src/features.c
@@ -22,6 +22,10 @@
 #include <proj_api.h>
 #endif
 
+#if defined(HAVE_LIBCMOR)
+#include "cmor.h"
+#endif
+
 #include <stdio.h>
 #include <string.h>
 
@@ -41,8 +45,12 @@ void printFeatures(void)
 #endif
 #if defined(_OPENMP)
   fprintf(stderr, " OpenMP");
-#if defined(HAVE_OPENMP4)
+#if defined(HAVE_OPENMP45)
+  fprintf(stderr, "45");
+#elif defined(HAVE_OPENMP4)
   fprintf(stderr, "4");
+#elif defined(HAVE_OPENMP3)
+  fprintf(stderr, "3");
 #endif
 #endif
 #if  defined(HAVE_LIBHDF5)
@@ -63,9 +71,11 @@ void printFeatures(void)
 #if defined(HAVE_LIBSZ)
   fprintf(stderr, " SZ");
 #endif
+  /*
 #if defined(HAVE_LIBZ)
   fprintf(stderr, " Z");
 #endif
+  */
 #if defined(HAVE_LIBJASPER)
   fprintf(stderr, " JASPER");
 #endif
@@ -144,6 +154,13 @@ void printLibraries(void)
   fprintf(stderr, "/%g", PJ_VERSION*0.01);
 #endif
 #endif
+  
+#if defined(HAVE_LIBCMOR)
+  fprintf(stderr, " CMOR");
+#if defined(CMOR_VERSION_MAJOR)
+  fprintf(stderr, "/%u.%u.%u", CMOR_VERSION_MAJOR, CMOR_VERSION_MINOR, CMOR_VERSION_PATCH);
+#endif
+#endif
 
 #if defined(HAVE_LIBXML2)
   fprintf(stderr, " xml2");
diff --git a/src/field.h b/src/field.h
index 6c07c28..ec30bbb 100644
--- a/src/field.h
+++ b/src/field.h
@@ -35,7 +35,7 @@ enum field_flag {
 
 #define  MADDMN(x,y)  (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)+(y))
 #define  MSUBMN(x,y)  (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)-(y))
-#define  MMULMN(x,y)  (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)*(y))
+#define  MMULMN(x,y)  (DBL_IS_EQUAL((x),0.)||DBL_IS_EQUAL((y),0.) ? 0 : DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)*(y))
 #define  MDIVMN(x,y)  (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) || DBL_IS_EQUAL((y),0.) ? missval1 : (x)/(y))
 #define  MPOWMN(x,y)  (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : pow((x),(y)))
 #define  MSQRTMN(x)   (DBL_IS_EQUAL((x),missval1) || (x)<0 ? missval1 : sqrt(x))
@@ -51,7 +51,7 @@ enum field_flag {
 
 #define  ADDM(x,y)  (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : (x)+(y))
 #define  SUBM(x,y)  (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : (x)-(y))
-#define  MULM(x,y)  (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : (x)*(y))
+#define  MULM(x,y)  (IS_EQUAL((x),0.)||IS_EQUAL((y),0.) ? 0 : IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : (x)*(y))
 #define  DIVM(x,y)  (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) || IS_EQUAL((y),0.) ? missval1 : (x)/(y))
 #define  POWM(x,y)  (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : pow((x),(y)))
 #define  SQRTM(x)   (IS_EQUAL((x),missval1) || (x)<0 ? missval1 : sqrt(x))
diff --git a/src/fieldc.c b/src/fieldc.c
index d6846c0..6156bc0 100644
--- a/src/fieldc.c
+++ b/src/fieldc.c
@@ -147,7 +147,7 @@ void farround(field_t *field)
   int len = gridInqSize(grid);
 
   for ( int i = 0; i < len; i++ ) 
-    array[i] = round(array[i]);
+    array[i] = (double)lround(array[i]);
 
   field->nmiss = 0;
   for ( int i = 0; i < len; i++ )
diff --git a/src/gradsdeslib.c b/src/gradsdeslib.c
index 7dcb47a..97a11b7 100644
--- a/src/gradsdeslib.c
+++ b/src/gradsdeslib.c
@@ -363,11 +363,8 @@ static const char *mons[12] = {"jan","feb","mar","apr","may","jun",
 
 char *adtprs (char *ch, struct dt *def, struct dt *dtim) {
 gaint val,flag,i;
-char *pos;
 char monam[5];
 
-  pos = ch;
-
   dtim->mn = 0;
   dtim->hr = 0;
   dtim->dy = 1;
@@ -485,11 +482,8 @@ char monam[5];
 
 char *rdtprs (char *ch, struct dt *dtim) {
 gaint flag,val;
-char *pos;
 char id[3];
 
-  pos = ch;
-
   dtim->yr = 0;
   dtim->mo = 0;
   dtim->dy = 0;
@@ -639,9 +633,7 @@ char *ch;
    encountered.  The word is terminated with '\0'. ch2 is src, ch1 is dest */
 
 void getwrd (char *ch1, char *ch2, int len) {
-char *ch;
 
-  ch = ch1;
   while (len>0 && *ch2!='\n' && *ch2!='\0' && *ch2!='\r' && *ch2!=' ' ) {
     *ch1 = *ch2;
     len--;
@@ -952,10 +944,9 @@ char *gafndt (char *fn, struct dt *dtim, struct dt *dtimi, gadouble *vals,
               struct gachsub *pch1st, struct gaens *ens1st, gaint t, gaint e, gaint *flag) {
 struct gachsub *pchsub;
 struct gaens *ens;
-struct dt stim;
 gaint len,olen,iv,tdif,i,tused,eused;
 char *fnout, *in, *out, *work, *in2, *out2;
-
+  (void)vals;
   tused = eused = 0;
   olen = 0;
   while (*(fn+olen)) olen++;
@@ -1107,11 +1098,6 @@ char *fnout, *in, *out, *work, *in2, *out2;
     /* forecast times */
     else if (*in=='%' && *(in+1)=='f' && *(in+2)=='2') {
       tused=1;
-      stim.yr = (gaint)(*vals+0.1);
-      stim.mo = (gaint)(*(vals+1)+0.1);
-      stim.dy = (gaint)(*(vals+2)+0.1);
-      stim.hr = (gaint)(*(vals+3)+0.1);
-      stim.mn = (gaint)(*(vals+4)+0.1);
       tdif = timdif(dtimi,dtim);
       tdif = (tdif+30)/60;
       if (tdif<99) sprintf (out,"%02i",tdif);
@@ -1120,11 +1106,6 @@ char *fnout, *in, *out, *work, *in2, *out2;
       in+=3;
     } else if (*in=='%' && *(in+1)=='f' && *(in+2)=='3') {
       tused=1;
-      stim.yr = (gaint)(*vals+0.1);
-      stim.mo = (gaint)(*(vals+1)+0.1);
-      stim.dy = (gaint)(*(vals+2)+0.1);
-      stim.hr = (gaint)(*(vals+3)+0.1);
-      stim.mn = (gaint)(*(vals+4)+0.1);
       tdif = timdif(dtimi,dtim); 
       tdif = (tdif+30)/60;
       if (tdif<999) sprintf (out,"%03i",tdif);
@@ -1234,8 +1215,8 @@ int read_gradsdes(char *filename, dsets_t *pfi)
   char rec[MAX_RECLEN], mrec[MAX_RECLEN];
   char *ch, *pos;
   int i, j, ii, jj;
-  off_t levs,acum,acumvz,recacm;
-  gaint acumstride=0;
+  off_t levs,acum,recacm;
+  // gaint acumstride=0;
   gaint hdrb, trlb;
   gaint size=0,rc,len,flag,tim1,tim2;
   gaint flgs[8],e,t;
@@ -1628,14 +1609,14 @@ int read_gradsdes(char *filename, dsets_t *pfi)
               tdef.mo = -1000;
               tdef.dy = -1000;
               if ( (pos = adtprs(ch,&tdef,&dt1))==NULL) goto err3b_tdef;
-              if (*pos!=' ' || dt1.yr == -1000 || dt1.mo == -1000.0 ||
+              if (*pos!=' ' || dt1.yr == -1000 || dt1.mo == -1000 ||
                   dt1.dy == -1000) goto err3c_tdef;
               if ( (ch = nxtwrd(ch))==NULL) goto err4a_tdef;
               if ( (pos = rdtprs(ch,&dt2))==NULL) goto err4b_tdef;
               v1 = (dt2.yr * 12) + dt2.mo;
               v2 = (dt2.dy * 1440) + (dt2.hr * 60) + dt2.mn;
               /* check if 0 dt */
-              if ( (v1 == 0) && (v2 == 0) ) goto err4c_tdef;  
+              if ( ((int)v1 == 0) && ((int)v2 == 0) ) goto err4c_tdef;  
               if ((vals = (gadouble *)galloc(sizeof(gadouble)*8,"tvals5")) == NULL) goto err8; 
               *(vals) = dt1.yr;
               *(vals+1) = dt1.mo;
@@ -1882,7 +1863,7 @@ int read_gradsdes(char *filename, dsets_t *pfi)
           goto err9;
         }
     }
-
+  (void) flgs;
   /* Done scanning!
      Check if scanned stuff makes sense, and then set things up correctly */
 
@@ -2025,14 +2006,13 @@ int read_gradsdes(char *filename, dsets_t *pfi)
     pvar->recoff = 0;
     recacm = 0;
     pvar++;
-    acumvz=acum;
 
     for (i=1; i<pfi->vnum; i++) {
       if (pvar->var_t) {   
         acum = acum + levs*(pfi->gsiz)*(pfi->dnum[3]); 
       } else {                              
         acum = acum + (levs*pfi->gsiz);
-        acumstride = acum ;
+        // acumstride = acum ;
       }
       recacm += levs;
       pvar->offset = acum;
@@ -2209,11 +2189,6 @@ int read_gradsdes(char *filename, dsets_t *pfi)
   gaprnt (0," starting value\n");
   goto err9;
 
- err3:
-  gaprnt (0,"Open Error:  Missing or invalid dimension");
-  gaprnt (0," starting value\n");
-  goto err9;
-
  err4a_tdef:
   gaprnt (0,"Open Error:  Time increment missing in tdef\n");
   gaprnt (0," use 1 for single time data\n");
@@ -2238,30 +2213,6 @@ int read_gradsdes(char *filename, dsets_t *pfi)
   gaprnt (0,"Open Error:  Invalid variable record\n");
   goto err9;
 
- err6a:
-  gaprnt (0,"Open Error:  Invalid x,y pair\n");
-  goto err9;
-
- err7a: 
-  gaprnt (0,"Open Error:  EOF occurred reading ensemble names\n");
-  goto err9;
-
- err7b:
-  gaprnt (0,"Open Error:  Blank record found in EDEF data\n");
-  goto err9;
-
- err7c:
-  gaprnt (0,"Open Error:  Invalid ensemble grib codes\n");
-  goto err9;
-
- err7d:
-  gaprnt (0,"Open Error:  Invalid ensemble name\n");
-  goto err9;
-
- err7e:
-  gaprnt (0,"Open Error:  Invalid ensemble record\n");
-  goto err9;
-
  err8:
   gaprnt (0,"Open Error:  Memory allocation Error in gaddes.c\n");
   goto retrn;
diff --git a/src/grid.c b/src/grid.c
index 411ea6e..e8ab4cb 100644
--- a/src/grid.c
+++ b/src/grid.c
@@ -962,19 +962,19 @@ int gridToCurvilinear(int gridID1, int lbounds)
 
 	if ( gridtype == GRID_LAEA )
 	  {
-	    int lvalid_xunits = FALSE;
-	    int lvalid_yunits = FALSE;
+	    bool lvalid_xunits = false;
+	    bool lvalid_yunits = false;
 	    int len;
 	    len = (int) strlen(xunits);
-	    if ( len == 1 && memcmp(xunits, "m",  1) == 0 ) lvalid_xunits = TRUE;
-	    if ( len == 2 && memcmp(xunits, "km", 2) == 0 ) lvalid_xunits = TRUE;
+	    if ( len == 1 && memcmp(xunits, "m",  1) == 0 ) lvalid_xunits = true;
+	    if ( len == 2 && memcmp(xunits, "km", 2) == 0 ) lvalid_xunits = true;
 	    len = (int) strlen(yunits);
-	    if ( len == 1 && memcmp(yunits, "m",  1) == 0 ) lvalid_yunits = TRUE;
-	    if ( len == 2 && memcmp(yunits, "km", 2) == 0 ) lvalid_yunits = TRUE;
+	    if ( len == 1 && memcmp(yunits, "m",  1) == 0 ) lvalid_yunits = true;
+	    if ( len == 2 && memcmp(yunits, "km", 2) == 0 ) lvalid_yunits = true;
 
-	    if ( lvalid_xunits == FALSE )
+	    if ( lvalid_xunits == false )
 	      cdoWarning("Possibly wrong result! Invalid x-coordinate units: \"%s\" (expected \"m\" or \"km\")", xunits);
-	    if ( lvalid_yunits == FALSE )
+	    if ( lvalid_yunits == false )
 	      cdoWarning("Possibly wrong result! Invalid y-coordinate units: \"%s\" (expected \"m\" or \"km\")", yunits);
 	  }
 
@@ -987,7 +987,6 @@ int gridToCurvilinear(int gridID1, int lbounds)
 	double *xvals2D = (double*) Malloc(gridsize*sizeof(double));
 	double *yvals2D = (double*) Malloc(gridsize*sizeof(double));
 
-
 	if ( gridtype == GRID_LCC )
 	  {
 	    for ( int j = 0; j < ny; j++ )
@@ -1233,6 +1232,109 @@ int gridToCurvilinear(int gridID1, int lbounds)
 }
 
 
+int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionIndexList, int nocoords, int nobounds)
+{
+
+  /* transform input grid into a unstructured Version if necessary {{{ */
+  int unstructuredGridID;
+  if (GRID_UNSTRUCTURED == gridInqType(gridID1))
+  {
+    unstructuredGridID = gridID1;
+  }
+  else
+  {
+    unstructuredGridID = gridToUnstructured(gridID1,!nobounds);
+  }
+  int unstructuredGridSize = gridInqSize(unstructuredGridID);
+
+  int unstructuredSelectionGridID = gridCreate(GRID_UNSTRUCTURED,selectionSize);
+
+  if ( nocoords ) return (unstructuredSelectionGridID);
+  /* }}} */
+
+  /* copy meta data of coordinates {{{*/
+  char xname[CDI_MAX_NAME], xlongname[CDI_MAX_NAME], xunits[CDI_MAX_NAME];
+  char yname[CDI_MAX_NAME], ylongname[CDI_MAX_NAME], yunits[CDI_MAX_NAME];
+
+  gridInqXname(unstructuredGridID, xname);
+  gridInqXlongname(unstructuredGridID, xlongname);
+  gridInqXunits(unstructuredGridID, xunits);
+  gridInqYname(unstructuredGridID, yname);
+  gridInqYlongname(unstructuredGridID, ylongname);
+  gridInqYunits(unstructuredGridID, yunits);
+
+  gridDefXname(unstructuredSelectionGridID, xname);
+  gridDefXlongname(unstructuredSelectionGridID, xlongname);
+  gridDefXunits(unstructuredSelectionGridID, xunits);
+  gridDefYname(unstructuredSelectionGridID, yname);
+  gridDefYlongname(unstructuredSelectionGridID, ylongname);
+  gridDefYunits(unstructuredSelectionGridID, yunits);
+  /* }}} */
+
+  /* TODO: select bounds */
+
+  /* copy relevant coordinate {{{ */
+  double *xvalsUnstructured = (double*) Malloc(unstructuredGridSize*sizeof(double));
+  double *yvalsUnstructured = (double*) Malloc(unstructuredGridSize*sizeof(double));
+  gridInqXvals(unstructuredGridID, xvalsUnstructured);
+  gridInqYvals(unstructuredGridID, yvalsUnstructured);
+
+
+  gridDefXsize(unstructuredSelectionGridID, selectionSize);
+  gridDefYsize(unstructuredSelectionGridID, selectionSize);
+  double *xvals   = (double*) Malloc(selectionSize*sizeof(double));
+  double *yvals   = (double*) Malloc(selectionSize*sizeof(double));
+
+  for (int i = 0; i < selectionSize; i++)
+  {
+    xvals[i] = xvalsUnstructured[selectionIndexList[i]];
+    yvals[i] = yvalsUnstructured[selectionIndexList[i]];
+    /*
+    cdoPrint("xval[%d](%d) = %g",i,selectionIndexList[i],xvals[i]);
+    cdoPrint("yval[%d](%d) = %g",i,selectionIndexList[i],yvals[i]);
+    */
+  }
+  gridDefXvals(unstructuredSelectionGridID,xvals);
+  gridDefYvals(unstructuredSelectionGridID,yvals);
+  /* }}} */
+
+  /* copy bounds if requested {{{ */
+  if ( ! nobounds )
+  {
+    int nvertex                 = gridInqNvertex(unstructuredGridID);
+    double *xbounds             = (double*) Malloc(nvertex*selectionSize*sizeof(double));
+    double *ybounds             = (double*) Malloc(nvertex*selectionSize*sizeof(double));
+    double *xboundsUnstructured = (double*) Malloc(nvertex*unstructuredGridSize*sizeof(double));
+    double *yboundsUnstructured = (double*) Malloc(nvertex*unstructuredGridSize*sizeof(double));
+    gridInqXbounds(unstructuredGridID, xboundsUnstructured);
+    gridInqYbounds(unstructuredGridID, yboundsUnstructured);
+    for (int i = 0; i < selectionSize; i++)
+    {
+      for (int k = 0; k < nvertex; k++)
+      {
+        xbounds[i*nvertex+k] = xboundsUnstructured[selectionIndexList[i]*nvertex+k];
+        ybounds[i*nvertex+k] = yboundsUnstructured[selectionIndexList[i]*nvertex+k];
+      }
+    }
+    gridDefNvertex(unstructuredSelectionGridID,nvertex);
+    gridDefXbounds(unstructuredSelectionGridID,xbounds);
+    gridDefYbounds(unstructuredSelectionGridID,ybounds);
+
+    Free(xboundsUnstructured);
+    Free(yboundsUnstructured);
+    Free(xbounds);
+    Free(ybounds);
+  }
+  /* }}} */
+
+  Free(xvalsUnstructured);
+  Free(yvalsUnstructured);
+  Free(xvals);
+  Free(yvals);
+
+  return (unstructuredSelectionGridID);
+}
+
 int gridToUnstructured(int gridID1, int lbounds)
 {
   int gridtype = gridInqType(gridID1);
@@ -1714,3 +1816,23 @@ int gridWeights(int gridID, double *grid_wgts)
 
   return w_status;
 }
+
+
+bool grid_is_distance_generic(int gridID)
+{
+  bool status = false;
+
+  if ( gridInqType(gridID) == GRID_GENERIC )
+    {
+      char xunits[CDI_MAX_NAME];
+      gridInqXunits(gridID, xunits);
+      char yunits[CDI_MAX_NAME];
+      gridInqXunits(gridID, yunits);
+
+      if ( strcmp(xunits, "m") == 0 && strcmp(yunits, "m") == 0 &&
+           gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
+        status = true;
+    }
+
+  return status;
+}
diff --git a/src/grid.h b/src/grid.h
index aaaeea3..09d9323 100644
--- a/src/grid.h
+++ b/src/grid.h
@@ -5,8 +5,11 @@
 #include "config.h"
 #endif
 
+#include <math.h>
+#include <stdbool.h>
+
 #ifndef  M_PI
-#define  M_PI        3.14159265358979323846  /* pi */
+#define  M_PI        3.14159265358979323846264338327950288  /* pi */
 #endif
 
 
@@ -19,6 +22,8 @@
 #endif
 
 
+bool grid_is_distance_generic(int gridID);
+
 void grid_to_radian(const char *units, long nvals, double *restrict values, const char *description);
 void grid_to_degree(const char *units, long nvals, double *restrict values, const char *description);
 
@@ -41,6 +46,7 @@ int referenceToGrid(int gridID);
 int gridToZonal(int gridID);
 int gridToMeridional(int gridID);
 int gridToUnstructured(int gridID, int lbounds);
+int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionIndexList, int nocoords ,int nobounds);
 int gridToCurvilinear(int gridID, int lbounds);
 int gridCurvilinearToRegular(int gridID);
 int gridToRegular(int gridID);
diff --git a/src/grid_gme.c b/src/grid_gme.c
index f78535c..0936d5e 100644
--- a/src/grid_gme.c
+++ b/src/grid_gme.c
@@ -61,28 +61,33 @@ void factorni(int kni, int *kni2, int *kni3)
   /*  kni3    INT      exponent of "3", either 0 or 1                   */
   /**********************************************************************/
 
-  int mx;
-
-  mx = kni;
+  unsigned lim = 9999;
+  int mx = kni;
   
   *kni2  = 0;
   *kni3  = 0;
 
-  while (mx > 1) { 
-      if (mx%2 == 0) {
-	*kni2 = *kni2 + 1;
-	mx    = mx/2;
-      } else if (mx%3 == 0) {
-	*kni3 = *kni3 + 1;
-	mx    = mx/3;
-      } else {
+  while ( mx > 1 && --lim )
+    {
+      if ( mx%2 == 0 )
+        {
+          *kni2 = *kni2 + 1;
+          mx    = mx/2;
+        }
+      else if ( mx%3 == 0 )
+        {
+          *kni3 = *kni3 + 1;
+          mx    = mx/3;
+        }
+      else
+        {
 	/* error return */
-      }
-  }
+        }
+    }
 
   /* kni3 must not be greater than */
   
-  if (*kni3 > 1) {
+  if ( *kni3 > 1 ) {
     /* error return */
   }
 }
@@ -110,7 +115,7 @@ int pow_ii(int x, int n)
       break;
   }
   
-  return (pow);
+  return pow;
 }
 
 /*****************************************************************************/
@@ -174,30 +179,25 @@ struct cart circum_center(struct cart *v0, struct cart *v1, struct cart *v2)
     ptmp2++;
   }
   
-  return (center);
+  return center;
 }
 
 /*****************************************************************************/
 
 struct cart gc2cc(struct geo *position)
 {
-  double cln;
-  double sln;
-  double clt;
-  double slt;
-  
   struct cart x;
 
-  sln = sin(position->lon);
-  cln = cos(position->lon);
-  slt = sin(position->lat);
-  clt = cos(position->lat);
+  double sln = sin(position->lon);
+  double cln = cos(position->lon);
+  double slt = sin(position->lat);
+  double clt = cos(position->lat);
 
   x.x[0] = cln*clt;
   x.x[1] = sln*clt;
   x.x[2] = slt;
 
-  return (x);
+  return x;
 }
 
 /*****************************************************************************/
@@ -241,7 +241,7 @@ struct geo cc2gc(struct cart *x)
     position.lat = atan(tlt);
   }
 
-  return (position);
+  return position;
 }
 
 /*****************************************************************************/
@@ -635,6 +635,7 @@ void tricntr(double *pxn,
              int kig1s, int kig1e, int kig2s, int kig2e, int knd, 
              int kjd, int kni)
 {
+  (void) knd;
   int id1, id2, id3, ioffset;
   double r1, r2, r3;
 
@@ -688,6 +689,7 @@ void gcpt(double *pxn,
           int kjd, double pgamma, 
           int ki1, int kj1, int ki2, int kj2, int ki, int kj)
 {
+  (void) knd;
   int id1, id2, id3, ioffset;
   double r1, r2, r3;
     
@@ -1224,7 +1226,6 @@ void initmask(int *mask, int ni, int nd)
 void gme_grid_restore(double *p, int ni, int nd)
 {
   int j, jd;
-    
   int tmp1, tmp2, tmp3, tmp4, tmp5;
 
   struct array pinfo;
@@ -1259,55 +1260,31 @@ void gme_grid_restore(double *p, int ni, int nd)
     switch (jd) {
     case 1:
       break;
+    case 2:
     case 3:
     case 4:
-    case 2:
-      for (j = 0; j <= ni; j++) {
-	p[j+tmp4+tmp5*jd+tmp3] = p[tmp4*(j+1)+tmp5*(jd-1)+tmp3];
-      }
+      for (j = 0; j <= ni; j++) p[j+tmp4+tmp5*jd+tmp3] = p[tmp4*(j+1)+tmp5*(jd-1)+tmp3];
       break;
     case 5:
-      for (j = 0; j <= ni; j++) {
-	p[j+tmp4+tmp5*jd+tmp3] = p[tmp4*(j+1)+tmp5*(jd-1)+tmp3];
-      }
-      for (j = 0; j <= ni; j++) {
-	p[tmp4*(j+1)+tmp5*5+tmp3] = p[j+tmp4+tmp5+tmp3];
-      }
+      for (j = 0; j <= ni; j++) p[j+tmp4+tmp5*jd+tmp3] = p[tmp4*(j+1)+tmp5*(jd-1)+tmp3];
+      for (j = 0; j <= ni; j++) p[tmp4*(j+1)+tmp5*5+tmp3] = p[j+tmp4+tmp5+tmp3];
       break;
     case 6:
-      for (j = 0; j <= ni; j++) {
-	p[j+tmp4*(ni+1)+tmp5*6+tmp3] = p[ni+tmp4*(ni+1-j)+tmp5*2+tmp3];
-      }
-      for (j = 0; j <= ni; j++) {
-	p[ni+tmp4*(j+1)+tmp5*6+tmp3] = p[ni-j+tmp4*(ni+1)+tmp5+tmp3];
-      }
+      for (j = 0; j <= ni; j++) p[j+tmp4*(ni+1)+tmp5*6+tmp3] = p[ni+tmp4*(ni+1-j)+tmp5*2+tmp3];
+      for (j = 0; j <= ni; j++) p[ni+tmp4*(j+1)+tmp5*6+tmp3] = p[ni-j+tmp4*(ni+1)+tmp5+tmp3];
       break;
+    case 7:
     case 8:
     case 9:
-    case 7:
-      for (j = 0; j <= ni; j++) {
-	p[j+tmp4*(ni+1)+tmp5*jd+tmp3] = p[ni+tmp4*(ni+1-j)+tmp5*(jd-4)+tmp3];
-      }
-      for (j = 0; j <= ni; j++) {
-	p[ni+tmp4*(j+1)+tmp5*jd+tmp3] = p[ni-j+tmp4*(ni+1)+tmp5*(jd-5)+tmp3];
-      }
-      for (j = 0; j <= ni; j++) {
-	p[j+tmp4+tmp5*jd+tmp3] = p[tmp4*(j+1)+tmp5*(jd-1)+tmp3];
-      }
+      for (j = 0; j <= ni; j++) p[j+tmp4*(ni+1)+tmp5*jd+tmp3] = p[ni+tmp4*(ni+1-j)+tmp5*(jd-4)+tmp3];
+      for (j = 0; j <= ni; j++) p[ni+tmp4*(j+1)+tmp5*jd+tmp3] = p[ni-j+tmp4*(ni+1)+tmp5*(jd-5)+tmp3];
+      for (j = 0; j <= ni; j++) p[j+tmp4+tmp5*jd+tmp3] = p[tmp4*(j+1)+tmp5*(jd-1)+tmp3];
       break;
     case 10:
-      for (j = 0; j <= ni; j++) {
-	p[j+tmp4+tmp5*10+tmp3] = p[tmp4*(j+1)+tmp5*9+tmp3];
-      }
-      for (j = 0; j <= ni; j++) {
-	p[tmp4*(j+1)+tmp5*10+tmp3] = p[j+tmp4+tmp5*6+tmp3];
-      }
-      for (j = 0; j <= ni; j++) {
-	p[j+tmp4*(ni+1)+tmp5*10+tmp3] = p[ni+tmp4*(ni+1-j)+tmp5+tmp3];
-      }
-      for (j = 0; j <= ni; j++) {
-	p[ni+tmp4*(j+1)+tmp5*10+tmp3] = p[ni-j+tmp4*(ni+1)+tmp5*5+tmp3];
-      }
+      for (j = 0; j <= ni; j++) p[j+tmp4+tmp5*10+tmp3] = p[tmp4*(j+1)+tmp5*9+tmp3];
+      for (j = 0; j <= ni; j++) p[tmp4*(j+1)+tmp5*10+tmp3] = p[j+tmp4+tmp5*6+tmp3];
+      for (j = 0; j <= ni; j++) p[j+tmp4*(ni+1)+tmp5*10+tmp3] = p[ni+tmp4*(ni+1-j)+tmp5+tmp3];
+      for (j = 0; j <= ni; j++) p[ni+tmp4*(j+1)+tmp5*10+tmp3] = p[ni-j+tmp4*(ni+1)+tmp5*5+tmp3];
       break;
     }
   }
@@ -1584,6 +1561,6 @@ int main(int argc, char *argv[])
   Free(mask);
   Free(area);
 
-  return(0);
+  return 0;
 }
 */
diff --git a/src/grid_search.c b/src/grid_search.c
index 19b1e46..cd23e52 100644
--- a/src/grid_search.c
+++ b/src/grid_search.c
@@ -10,19 +10,31 @@
 #include "cdo_int.h"
 #include "dmemory.h"
 #include "util.h"
+#include "grid.h"
 #include "grid_search.h"
 
 
-#ifndef  M_PI
-#define  M_PI        3.14159265358979323846264338327950288  /* pi */
-#endif
-
 #define  PI       M_PI
 #define  PI2      (2.0*PI)
 
 
 static int gridsearch_method_nn = GS_KDTREE;
 
+static
+double cdo_default_search_radius(void)
+{
+  extern double gridsearch_radius;
+
+  double search_radius = gridsearch_radius;
+
+  if ( search_radius <    0. ) search_radius = 0.;
+  if ( search_radius >  180. ) search_radius = 180.;
+
+  search_radius = search_radius*DEG2RAD;
+
+  return search_radius;
+}
+
 static inline void LLtoXYZ_f(double lon, double lat, float *restrict xyz)
 {
    double cos_lat = cos(lat);
@@ -58,11 +70,11 @@ void gridsearch_set_method(const char *methodstr)
   else if ( strcmp(methodstr, "nearpt3") == 0 ) gridsearch_method_nn = GS_NEARPT3;
   else if ( strcmp(methodstr, "full")    == 0 ) gridsearch_method_nn = GS_FULL;
   else
-    cdoAbort("gridsearch method %s not available!\n", methodstr);
+    cdoAbort("gridsearch method %s not available!", methodstr);
 }
 
 
-struct gridsearch *gridsearch_create_reg2d(unsigned lcyclic, unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats)
+struct gridsearch *gridsearch_create_reg2d(bool lcyclic, unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats)
 {
   struct gridsearch *gs = (struct gridsearch *) Calloc(1, sizeof(struct gridsearch));
 
@@ -105,6 +117,8 @@ struct gridsearch *gridsearch_create_reg2d(unsigned lcyclic, unsigned nx, unsign
   gs->coslat = coslat;
   gs->sinlat = sinlat;
 
+  gs->search_radius = cdo_default_search_radius();
+
   return gs;
 }
 
@@ -243,6 +257,8 @@ struct gridsearch *gridsearch_create(unsigned n, const double *restrict lons, co
 
   gs->kdt  = gs_create_kdtree(n, lons, lats);
 
+  gs->search_radius = cdo_default_search_radius();
+
   return gs;
 }
 
@@ -259,6 +275,8 @@ struct gridsearch *gridsearch_create_nn(unsigned n, const double *restrict lons,
   else if ( gs->method_nn == GS_NEARPT3 ) gs->near = gs_create_nearpt3(n, lons, lats);
   else if ( gs->method_nn == GS_FULL    ) gs->full = gs_create_full(n, lons, lats);
 
+  gs->search_radius = cdo_default_search_radius();
+
   return gs;
 }
 
@@ -444,6 +462,7 @@ struct pqueue *gridsearch_qnearest(struct gridsearch *gs, double lon, double lat
       // printf("range %g %g %g %p\n", lon, lat, range, node);
 
       float frange = KDATA_INVSCALE(range);
+      /*
       if ( !(frange < range0) )
         {
           if ( result )
@@ -455,8 +474,191 @@ struct pqueue *gridsearch_qnearest(struct gridsearch *gs, double lon, double lat
             }
           result = NULL;
         }
+      */
       if ( prange ) *prange = frange;
     }
   
   return result;
 }
+
+#define  BIGNUM   1.e+20
+#define  TINY     1.e-14
+
+static
+void knn_store_distance(int nadd, double distance, int num_neighbors, int *restrict nbr_add, double *restrict nbr_dist)
+{
+  if ( num_neighbors == 1 )
+    {
+      if ( distance < nbr_dist[0] || (distance <= nbr_dist[0] && nadd < nbr_add[0]) )
+	{
+	  nbr_add[0]  = nadd;
+	  nbr_dist[0] = distance;
+	}
+    }
+  else
+    {
+      for ( int nchk = 0; nchk < num_neighbors; ++nchk )
+	{
+	  if ( distance < nbr_dist[nchk] || (distance <= nbr_dist[nchk] && nadd < nbr_add[nchk]) )
+	    {
+	      for ( int n = num_neighbors-1; n > nchk; --n )
+		{
+		  nbr_add[n]  = nbr_add[n-1];
+		  nbr_dist[n] = nbr_dist[n-1];
+		}
+	      nbr_add[nchk]  = nadd;
+	      nbr_dist[nchk] = distance;
+	      break;
+	    }
+	}
+    }
+}
+
+static
+void knn_check_distance(int num_neighbors, const int *restrict nbr_add, double *restrict nbr_dist)
+{
+  // If distance is zero, set to small number
+  for ( int nchk = 0; nchk < num_neighbors; ++nchk )
+    if ( nbr_add[nchk] >= 0 && nbr_dist[nchk] <= 0. ) nbr_dist[nchk] = TINY;
+}
+
+
+void gridsearch_knn_init(struct gsknn *knn)
+{
+  unsigned ndist = knn->ndist;
+  int *restrict add = knn->add;
+  double *restrict dist = knn->dist;
+
+  for ( unsigned i = 0; i < ndist; ++i )
+    {
+      add[i]  = -1;
+      dist[i] = BIGNUM;
+    }
+}
+
+
+struct gsknn *gridsearch_knn_new(unsigned size)
+{
+  struct gsknn *knn = (struct gsknn *) Malloc(sizeof(struct gsknn));
+  
+  knn->ndist   = size;
+  knn->size    = size;
+  knn->mask    = (int*) Malloc(size*sizeof(int));       // mask at nearest neighbors
+  knn->add     = (int*) Malloc(size*sizeof(int));       // source address at nearest neighbors
+  knn->dist    = (double*) Malloc(size*sizeof(double)); // angular distance of the nearest neighbors
+  knn->tmpadd  = NULL;
+  knn->tmpdist = NULL;
+
+  gridsearch_knn_init(knn);
+
+  return knn;
+}
+
+
+void gridsearch_knn_delete(struct gsknn *knn)
+{
+  if ( knn )
+    {
+      knn->size = 0;
+      if ( knn->dist    ) Free(knn->dist);
+      if ( knn->add     ) Free(knn->add);
+      if ( knn->tmpdist ) Free(knn->tmpdist);
+      if ( knn->tmpadd  ) Free(knn->tmpadd);
+      if ( knn->mask    ) Free(knn->mask);
+      Free(knn);
+    }
+}
+
+
+int gridsearch_knn(struct gridsearch *gs, struct gsknn *knn, double plon, double plat)
+{
+  /*
+    Output variables:
+
+    int nbr_add[num_neighbors]     ! address of each of the closest points
+    double nbr_dist[num_neighbors] ! distance to each of the closest points
+
+    Input variables:
+
+    double plat,         ! latitude  of the search point
+    double plon,         ! longitude of the search point
+  */
+
+  double search_radius = gs->search_radius;
+
+  // Initialize distance and address arrays
+  gridsearch_knn_init(knn);
+
+  int num_neighbors = knn->size;
+  int *restrict nbr_add = knn->add;
+  double *restrict nbr_dist = knn->dist;
+
+  int ndist = num_neighbors;
+  // check some more points if distance is the same use the smaller index (nadd)
+  if ( ndist > 8 ) ndist += 8;
+  else             ndist *= 2; 
+  if ( ndist > (int)gs->n ) ndist = gs->n;
+
+  if ( knn->tmpadd  == NULL ) knn->tmpadd  = (int*) Malloc(ndist*sizeof(int));
+  if ( knn->tmpdist == NULL ) knn->tmpdist = (double*) Malloc(ndist*sizeof(double));
+
+  int *adds = knn->tmpadd;
+  double *dist = knn->tmpdist;
+  
+  const double range0 = SQR(search_radius);
+  double range = range0;
+
+  int j = 0;
+
+  if ( num_neighbors == 1 )
+    {
+      unsigned nadd = gridsearch_nearest(gs, plon, plat, &range);
+      if ( nadd != GS_NOT_FOUND )
+        {
+          //if ( range < range0 )
+            {
+              dist[j] = sqrt(range);
+              adds[j] = nadd;
+              j++;
+            }
+        }
+    }
+  else
+    {
+      struct pqueue *gs_result = gridsearch_qnearest(gs, plon, plat, &range, ndist);
+      if ( gs_result )
+        {
+          unsigned nadd;
+          struct resItem *p;
+          while ( pqremove_min(gs_result, &p) )
+            {
+              nadd  = p->node->index;
+              range = p->dist_sq;
+              Free(p); // Free the result node taken from the heap
+
+              if ( range < range0 )
+                {
+                  dist[j] = sqrt(range);
+                  adds[j] = nadd;
+                  j++;
+                }
+            }
+          Free(gs_result->d); // free the heap
+          Free(gs_result);    // and free the heap information structure
+        }
+    }
+
+  ndist = j;
+  int max_neighbors = ( ndist < num_neighbors ) ? ndist : num_neighbors;
+
+  for ( j = 0; j < ndist; ++j )
+    knn_store_distance(adds[j], dist[j], max_neighbors, nbr_add, nbr_dist);
+
+  knn_check_distance(max_neighbors, nbr_add, nbr_dist);
+
+  if ( ndist > num_neighbors ) ndist = num_neighbors;
+
+  knn->ndist = ndist;
+
+  return ndist;
+} // gridsearch_knn
diff --git a/src/grid_search.h b/src/grid_search.h
index b973c54..dbc8729 100644
--- a/src/grid_search.h
+++ b/src/grid_search.h
@@ -1,6 +1,7 @@
 #ifndef _GRID_SEARCH_H_
 #define _GRID_SEARCH_H_
 
+#include <stdbool.h>
 #include <limits.h>
 #include "kdtreelib/kdtree.h"
 #include "nearpt3c.h"
@@ -31,19 +32,32 @@ struct gridsearch {
   unsigned nx, ny;
 
   struct gsNear *near;
-
   struct kdNode *kdt;
-
   struct gsFull *full;
 
+  double search_radius;
+
   // reg2d search
   double *reg2d_center_lon, *reg2d_center_lat;
   double *coslat, *sinlat;   // cosine, sine of grid lats (for distance)
   double *coslon, *sinlon;   // cosine, sine of grid lons (for distance)
 };
 
+struct gsknn {
+  unsigned ndist;
+  unsigned size;
+  int     *mask;
+  int     *add;
+  int     *tmpadd;
+  double  *dist;
+  double  *tmpdist;
+};
+
+struct gsknn *gridsearch_knn_new(unsigned size);
+void gridsearch_knn_delete(struct gsknn *knn);
+int gridsearch_knn(struct gridsearch *gs, struct gsknn *knn, double plon, double plat);
 
-struct gridsearch *gridsearch_create_reg2d(unsigned lcyclic, unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats);
+struct gridsearch *gridsearch_create_reg2d(bool lcyclic, unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats);
 struct gridsearch *gridsearch_create(unsigned n, const double *restrict lons, const double *restrict lats);
 struct gridsearch *gridsearch_create_nn(unsigned n, const double *restrict lons, const double *restrict lats);
 void gridsearch_delete(struct gridsearch *gs);
diff --git a/src/griddes.c b/src/griddes.c
index 6e83343..29e8bed 100644
--- a/src/griddes.c
+++ b/src/griddes.c
@@ -161,7 +161,7 @@ int getoptname(char *optname, const char *optstring, int nopt)
   else
     nerr = 1;
 
-  return (nerr);
+  return nerr;
 }
 
 
@@ -514,7 +514,7 @@ int gridDefine(griddes_t grid)
   if ( grid.ylongname[0] ) gridDefYlongname(gridID, grid.ylongname);
   if ( grid.yunits[0]    ) gridDefYunits(gridID, grid.yunits);
 
-  return (gridID);
+  return gridID;
 }
 
 static
@@ -524,7 +524,7 @@ char *skipSeparator(char *pline)
   if ( *pline == '=' || *pline == ':' ) pline++;
   while ( isspace((int) *pline) ) pline++;
 
-  return (pline);
+  return pline;
 }
 
 
@@ -616,7 +616,7 @@ double *readfield(griddes_t *grid, int record, char *format, char *filename)
   else
     Error("format %s unsupported!", format);
 
-  return (vals);
+  return vals;
 }
 */
 /*
@@ -652,7 +652,7 @@ double *readfield4(griddes_t *grid, int record, char *format, char *filename)
   else
     Error("format %s unsupported!", format);
 
-  return (vals);
+  return vals;
 }
 */
 
@@ -665,7 +665,7 @@ double readflt(const char *filename, const char *name, const char *pline)
   if ( pline == endptr )
     cdoAbort("Couldn't read value for %s (grid description file: %s)!", name, filename);
  
-  return (val);
+  return val;
 }
 
 
@@ -677,11 +677,13 @@ int gridFromFile(FILE *gfp, const char *dname)
   int lerror;
   size_t i, len;
   griddes_t grid;
+  int lineno = 0;
 
   gridInit(&grid);
 
   while ( readline(gfp, line, MAX_LINE_LEN) )
     {
+      lineno++;
       if ( line[0] == '#' ) continue;
       if ( line[0] == '\0' ) continue;
       len = strlen(line);
@@ -987,8 +989,9 @@ int gridFromFile(FILE *gfp, const char *dname)
 	  grid.yvals = (double*) Malloc(grid.size*sizeof(double));
 	  for ( i = 0; i < (int) grid.size; i++ )
 	    {
+              lineno++;
 	      if ( ! readline(gfp, line, MAX_LINE_LEN) )
-		cdoAbort("Incomplete command: >gridlatlon< (grid description file: %s)", dname);
+		cdoAbort("Incomplete command: >gridlatlon< (line: %d file: %s)", lineno, dname);
 
 	      sscanf(line, "%lg %lg", &flat, &flon);
 	      grid.yvals[i] = flat;
@@ -1015,8 +1018,9 @@ int gridFromFile(FILE *gfp, const char *dname)
 		  lval = strtol(pline, &endptr, 10);
 		  if ( pline == endptr )
 		    {
+                      lineno++;
 		      if ( ! readline(gfp, line, MAX_LINE_LEN) )
-			cdoAbort("Incomplete command: >mask< (grid description file: %s)", dname);
+			cdoAbort("Incomplete command: >mask< (line: %d file: %s)", lineno, dname);
 
 		      pline = line;
 		      lval = strtol(pline, &endptr, 10);
@@ -1057,8 +1061,10 @@ int gridFromFile(FILE *gfp, const char *dname)
 		  fval = strtod(pline, &endptr);
 		  if ( pline == endptr )
 		    {
+                      lineno++;
 		      if ( ! readline(gfp, line, MAX_LINE_LEN) )
-			cdoAbort("Incomplete command: >xvals< (grid description file: %s)", dname);
+			cdoAbort("Incomplete command: >xvals< (line: %d file: %s)", lineno, dname);
+                      printf("%d %s\n", lineno, line);
 
 		      pline = line;
 		      fval = strtod(pline, &endptr);
@@ -1068,7 +1074,7 @@ int gridFromFile(FILE *gfp, const char *dname)
 		}
 	    }
 	  else
-	    cdoAbort("xsize or gridsize undefined (grid description file: %s)!", dname);
+	    cdoAbort("xsize or gridsize undefined (file: %s)!", dname);
 	}
       else if ( cmpstrlen(pline, "yvals", len)  == 0 )
 	{
@@ -1092,8 +1098,9 @@ int gridFromFile(FILE *gfp, const char *dname)
 		  fval = strtod(pline, &endptr);
 		  if ( pline == endptr )
 		    {
+                      lineno++;
 		      if ( ! readline(gfp, line, MAX_LINE_LEN) )
-			cdoAbort("Incomplete command: >yvals< (grid description file: %s)", dname);
+			cdoAbort("Incomplete command: >yvals< (line %d file: %s)", lineno, dname);
 
 		      pline = line;
 		      fval = strtod(pline, &endptr);
@@ -1133,8 +1140,9 @@ int gridFromFile(FILE *gfp, const char *dname)
 		  fval = strtod(pline, &endptr);
 		  if ( pline == endptr )
 		    {
+                      lineno++;
 		      if ( ! readline(gfp, line, MAX_LINE_LEN) )
-			cdoAbort("Incomplete command: >xbounds< (grid description file: %s)", dname);
+			cdoAbort("Incomplete command: >xbounds< (line %d file: %s)", lineno, dname);
 
 		      pline = line;
 		      fval = strtod(pline, &endptr);
@@ -1145,8 +1153,8 @@ int gridFromFile(FILE *gfp, const char *dname)
 	    }
 	  else
 	    {
-	      if ( size         == 0 ) cdoAbort("xsize or gridsize undefined (grid description file: %s)!", dname);
-	      if ( grid.nvertex == 0 ) cdoAbort("nvertex undefined (grid description file: %s)!", dname);
+	      if ( size         == 0 ) cdoAbort("xsize or gridsize undefined (file: %s)!", dname);
+	      if ( grid.nvertex == 0 ) cdoAbort("nvertex undefined (file: %s)!", dname);
 	    }
 	}
       else if ( cmpstrlen(pline, "ybounds", len)  == 0 )
@@ -1177,9 +1185,10 @@ int gridFromFile(FILE *gfp, const char *dname)
 		  fval = strtod(pline, &endptr);
 		  if ( pline == endptr )
 		    {
+                      lineno++;
 		      if ( ! readline(gfp, line, MAX_LINE_LEN) )
-			cdoAbort("Incomplete command: >ybounds< (grid description file: %s)", dname);
-
+			cdoAbort("Incomplete command: >ybounds< (line %d file: %s)", lineno, dname);
+                      
 		      pline = line;
 		      fval = strtod(pline, &endptr);
 		    }
@@ -1196,7 +1205,7 @@ int gridFromFile(FILE *gfp, const char *dname)
       else
 	{
 	  if ( grid.type != UNDEFID )
-	    cdoAbort("Invalid grid command : >%s< (grid description file: %s)", pline, dname);
+	    cdoAbort("Invalid grid command : >%s< (line %d file: %s)", pline, lineno, dname);
 	}
     }
   /*
@@ -1207,7 +1216,7 @@ int gridFromFile(FILE *gfp, const char *dname)
   */
   if ( grid.type != UNDEFID ) gridID = gridDefine(grid);
 
-  return (gridID);
+  return gridID;
 }
 
 
@@ -1235,28 +1244,23 @@ void skip_nondigit_lines(FILE *gfp)
 
 int input_ival(FILE *gfp, int *ival)
 {
-  int read_items;
-
   skip_nondigit_lines(gfp);
 
-  if ( feof(gfp) ) return(0);
+  if ( feof(gfp) ) return 0;
 
   *ival = 0;
-  read_items = fscanf(gfp, "%d", ival);
+  int read_items = fscanf(gfp, "%d", ival);
 
-  return (read_items);
+  return read_items;
 }
 
 
 int input_darray(FILE *gfp, int n_values, double *array)
 {
-  int i;
-  int read_items;
-
   if ( n_values <= 0 ) return 0;
 
-  read_items = 0;
-  for ( i = 0; i < n_values; i++ )
+  int read_items = 0;
+  for ( int i = 0; i < n_values; i++ )
     {
       skip_nondigit_lines(gfp);
 
@@ -1267,7 +1271,7 @@ int input_darray(FILE *gfp, int n_values, double *array)
       if ( feof(gfp) ) break;
     }
 
-  return (read_items);
+  return read_items;
 }
 
 
@@ -1281,8 +1285,8 @@ int gridFromPingo(FILE *gfp, const char *dname)
 
   gridInit(&grid);
 
-  if ( ! input_ival(gfp, &nlon) ) return (gridID);
-  if ( ! input_ival(gfp, &nlat) ) return (gridID);
+  if ( ! input_ival(gfp, &nlon) ) return gridID;
+  if ( ! input_ival(gfp, &nlat) ) return gridID;
 
   if ( nlon > 0 && nlon < 9999 && nlat > 0 && nlat < 9999 )
     {
@@ -1292,10 +1296,10 @@ int gridFromPingo(FILE *gfp, const char *dname)
       grid.xvals = (double*) Malloc(grid.xsize*sizeof(double));
       grid.yvals = (double*) Malloc(grid.ysize*sizeof(double));
 
-      if ( ! input_ival(gfp, &nlon) ) return (gridID);
+      if ( ! input_ival(gfp, &nlon) ) return gridID;
       if ( nlon == 2 )
 	{
-	  if ( input_darray(gfp, 2, grid.xvals) != 2 ) return (gridID);
+	  if ( input_darray(gfp, 2, grid.xvals) != 2 ) return gridID;
 	  grid.xvals[1] -= 360 * floor((grid.xvals[1] - grid.xvals[0]) / 360);
 
 	  if ( grid.xsize > 1 )
@@ -1307,7 +1311,7 @@ int gridFromPingo(FILE *gfp, const char *dname)
 	}
       else if ( nlon == (int)grid.xsize )
 	{
-	  if ( input_darray(gfp, nlon, grid.xvals) != nlon ) return (gridID);
+	  if ( input_darray(gfp, nlon, grid.xvals) != nlon ) return gridID;
 	  for ( i = 0; i < nlon - 1; i++ )
 	    if ( grid.xvals[i+1] <= grid.xvals[i] ) break;
 
@@ -1317,26 +1321,26 @@ int gridFromPingo(FILE *gfp, const char *dname)
 	      if ( i < nlon - 1 && grid.xvals[i+1] + 360 <= grid.xvals[i] )
 		{
 		  Message("Longitudes are not in ascending order!");
-		  return (gridID);
+		  return gridID;
 		}
 	    }
 	}
       else
-	return (gridID);
+	return gridID;
 
-      if ( ! input_ival(gfp, &nlat) ) return (gridID);
+      if ( ! input_ival(gfp, &nlat) ) return gridID;
       if ( nlat == 2 )
 	{
-	  if ( input_darray(gfp, 2, grid.yvals) != 2 ) return (gridID);
+	  if ( input_darray(gfp, 2, grid.yvals) != 2 ) return gridID;
 	  for ( i = 0; i < (int)grid.ysize; i++ )
 	    grid.yvals[i] = grid.yvals[0] + i*(grid.yvals[1] - grid.yvals[0]);
 	}
       else if ( nlat == (int)grid.ysize )
 	{
-	  if ( input_darray(gfp, nlat, grid.yvals) != nlat ) return (gridID);
+	  if ( input_darray(gfp, nlat, grid.yvals) != nlat ) return gridID;
 	}
       else
-	return (gridID);
+	return gridID;
 
       if ( grid.yvals[0]      >  90.001  || 
 	   grid.yvals[nlat-1] >  90.001  || 
@@ -1344,7 +1348,7 @@ int gridFromPingo(FILE *gfp, const char *dname)
 	   grid.yvals[nlat-1] < -90.001 )
 	{
 	  Message("Latitudes must be between 90 and -90!");
-	  return (gridID);
+	  return gridID;
 	}
 
       for ( i = 0; i < nlat - 1; i++ )
@@ -1352,7 +1356,7 @@ int gridFromPingo(FILE *gfp, const char *dname)
 	    ((grid.yvals[i+1] > grid.yvals[i]) != (grid.yvals[i+2] > grid.yvals[i+1]))) )
 	  {
 	    Message("Latitudes must be in descending or ascending order!");
-	    return (gridID);
+	    return gridID;
 	  }
 		    
       if ( nlat > 2 ) /* check if gaussian */
@@ -1381,7 +1385,7 @@ int gridFromPingo(FILE *gfp, const char *dname)
   
   if ( grid.type != UNDEFID ) gridID = gridDefine(grid);
 
-  return (gridID);
+  return gridID;
 }
 
 
@@ -1390,7 +1394,7 @@ int nfc2nlat(int nfc, int ntr)
   int nlat = nfc / (ntr+1);
   nlat /= 2;
 
-  return (nlat);
+  return nlat;
 }
 
 
@@ -1398,7 +1402,7 @@ int nlat2ntr(int nlat)
 {
   int ntr = (nlat*2 - 1) / 3;
 
-  return (ntr);
+  return ntr;
 }
 
 
@@ -1406,7 +1410,7 @@ int nlat2ntr_linear(int nlat)
 {
   int ntr = (nlat*2 - 1) / 2;
 
-  return (ntr);
+  return ntr;
 }
 
 
@@ -1423,7 +1427,7 @@ int ntr2nlat(int ntr)
       */
     }
 
-  return (nlat);
+  return nlat;
 }
 
 
@@ -1440,7 +1444,7 @@ int ntr2nlat_linear(int ntr)
       */
     }
 
-  return (nlat);
+  return nlat;
 }
 
 
@@ -1472,14 +1476,28 @@ int compNlon(int nlat)
 	}
     }
 
-  return (nlon);
+  return nlon;
 }
 
 static
 void gen_grid_lonlat(griddes_t *grid, const char *pline, double inc, double lon1, double lon2, double lat1, double lat2)
 {
   int gridtype = GRID_LONLAT;
-  int lbounds = TRUE;
+  bool lbounds = true;
+
+  if ( *pline != 0 && (*pline == '+' || *pline == '-') && (isdigit((int) *(pline+1)) || ispunct((int) *(pline+1))) )
+    {
+      char *endptr = (char *) pline;
+      double off = strtod(pline, &endptr);
+      pline = endptr;
+      
+      lon1 -= off;
+      lon2 += off;
+      lat1 -= off;
+      lat2 += off;
+      if ( lat1 < -90 ) lat1 = -90;
+      if ( lat2 >  90 ) lat2 =  90;
+    }
 
   if ( *pline != 0 )
     {
@@ -1505,7 +1523,7 @@ void gen_grid_lonlat(griddes_t *grid, const char *pline, double inc, double lon1
               pline++;
               if ( *pline == '0' )
                 {
-                  lbounds = FALSE;
+                  lbounds = false;
                   pline++;
                 }
             }
@@ -1515,7 +1533,7 @@ void gen_grid_lonlat(griddes_t *grid, const char *pline, double inc, double lon1
               pline++;
               if ( *pline == '0' )
                 {
-                  lbounds = FALSE;
+                  lbounds = false;
                   pline++;
                 }
             }
@@ -1527,6 +1545,9 @@ void gen_grid_lonlat(griddes_t *grid, const char *pline, double inc, double lon1
 
   grid->type = gridtype;
 
+  if ( lon1 >= lon2 || lat1 >= lat2 )
+    cdoAbort("Invalid grid box: lon1=%g lon2=%g lat1=%g lat2=%g", lon1, lon2, lat1, lat2);
+
   int nlon = (int) ((lon2 - lon1)/inc + 0.5);
   int nlat = (int) ((lat2 - lat1)/inc + 0.5);
 
@@ -1621,7 +1642,7 @@ int gridFromName(const char *gridname)
 	  else if ( cmpstrlen(pline, "spec", len) == 0 ) grid.type = GRID_SPECTRAL;
 	  else if ( cmpstrlen(pline, "",     len) == 0 ) grid.type = GRID_SPECTRAL;
       
-	  if ( pline[len] != 0 ) return (gridID);
+	  if ( pline[len] != 0 ) return gridID;
 
 	  if ( grid.type == GRID_GAUSSIAN )
 	    {
@@ -1649,7 +1670,7 @@ int gridFromName(const char *gridname)
 	  else if ( cmpstrlen(pline, "spec", len) == 0 ) grid.type = GRID_SPECTRAL;
 	  else if ( cmpstrlen(pline, "",     len) == 0 ) grid.type = GRID_SPECTRAL;
      
-	  if ( pline[len] != 0 ) return (gridID);
+	  if ( pline[len] != 0 ) return gridID;
 
 	  if ( grid.type == GRID_GAUSSIAN )
 	    {
@@ -1696,13 +1717,13 @@ int gridFromName(const char *gridname)
 	  grid.xvals[0] = atof(pline);
 	  while ( isdigit((int) *pline) || ispunct((int) *pline) || *pline == '-' ) pline++;
 	  if ( *pline == '_' ) pline++;
-	  if ( ! (pline[0] == 'l' &&  pline[1] == 'a' && pline[2] == 't') ) return(gridID);
+	  if ( ! (pline[0] == 'l' &&  pline[1] == 'a' && pline[2] == 't') ) return gridID;
 	  pline += 3;
 	  if ( *pline == '=' ) pline++;
 	  if ( isdigit((int) *pline) || ispunct((int) *pline) || *pline == '-' )
 	    grid.yvals[0] = atof(pline);
 	  else
-	    return (gridID);
+	    return gridID;
 	}
     }
   else if ( gridname[0] == 'g' && gridname[1] == 'm' && gridname[2] == 'e' ) /* gme<NI> */
@@ -1832,31 +1853,27 @@ int gridFromName(const char *gridname)
 
   if ( grid.type != -1 ) gridID = gridDefine(grid);
 
-  return (gridID);
+  return gridID;
 }
 
 
 int cdoDefineGrid(const char *gridfile)
 {
-  FILE *gfp;
-  char buffer[4];
   int gridID = -1;
   size_t len;
-  struct stat filestat;
-  int fileno;
-  int isreg = FALSE;
-  int lalloc = FALSE;
-  char *filename;
+  bool isreg = false;
+  bool lalloc = false;
 
-  filename = expand_filename(gridfile);
+  char *filename = expand_filename(gridfile);
   if ( filename )
-    lalloc = TRUE;
+    lalloc = true;
   else
     filename =  (char *) gridfile;
 
-  fileno = open(filename, O_RDONLY);
+  int fileno = open(filename, O_RDONLY);
   if ( fileno >= 0 )
     {
+      struct stat filestat;
       if ( fstat(fileno, &filestat) == 0 )
 	isreg = S_ISREG(filestat.st_mode);
     }
@@ -1871,6 +1888,7 @@ int cdoDefineGrid(const char *gridfile)
     }
   else
     {
+      char buffer[4];
       if ( read(fileno, buffer, 4) != 4 )
 	SysError("Read grid from %s failed!", filename);
 
@@ -1902,15 +1920,13 @@ int cdoDefineGrid(const char *gridfile)
 
       if ( gridID == -1 )
 	{
-	  int streamID;
 	  if ( cdoDebug ) cdoPrint("Grid from CDI file");
 	  openLock();
-	  streamID = streamOpenRead(filename);
+	  int streamID = streamOpenRead(filename);
 	  openUnlock();
 	  if ( streamID >= 0 )
 	    {
-	      int vlistID;
-	      vlistID = streamInqVlist(streamID);
+	      int vlistID = streamInqVlist(streamID);
 	      gridID  = vlistGrid(vlistID, 0);
 	      streamClose(streamID);
 	    }
@@ -1919,7 +1935,7 @@ int cdoDefineGrid(const char *gridfile)
       if ( gridID == -1 )
 	{
 	  if ( cdoDebug ) cdoPrint("grid from ASCII file");
-	  gfp = fopen(filename, "r");
+	  FILE *gfp = fopen(filename, "r");
 	  //size_t buffersize = 20*1024*1024;
 	  //char *buffer = (char*) Malloc(buffersize);
 	  //setvbuf(gfp, buffer, _IOFBF, buffersize);
@@ -1931,7 +1947,7 @@ int cdoDefineGrid(const char *gridfile)
       if ( gridID == -1 )
 	{
 	  if ( cdoDebug ) cdoPrint("grid from PINGO file");
-	  gfp = fopen(filename, "r");
+	  FILE *gfp = fopen(filename, "r");
 	  gridID = gridFromPingo(gfp, filename);
 	  fclose(gfp);
 	}
@@ -1941,7 +1957,7 @@ int cdoDefineGrid(const char *gridfile)
 
   if ( lalloc ) Free(filename);
 
-  return (gridID);
+  return gridID;
 }
 
 
diff --git a/src/interpol.c b/src/interpol.c
index 2bb727d..aaf1867 100644
--- a/src/interpol.c
+++ b/src/interpol.c
@@ -689,57 +689,60 @@ void intlinarr(long nxm, double *ym, double *xm, int nx, double *y, double *x)
 
 void intgridbil(field_t *field1, field_t *field2)
 {
-  int nlon1, nlat1;
-  int nlon2, nlat2;
-  int ilat;
-  int gridID1, gridID2;
-  int i, nmiss;
-  int lon_is_circular;
-  double *lon1, *lat1;
-  double **array1_2D = NULL;
-  double **field;
-  double *array = NULL;
-  double *array1, *array2;
-  double missval;
   char units[CDI_MAX_NAME];
-  /* static int index = 0; */
 
-  gridID1 = field1->grid;
-  gridID2 = field2->grid;
-  array1  = field1->ptr;
-  array2  = field2->ptr;
-  missval = field1->missval;
+  int gridID1 = field1->grid;
+  int gridID2 = field2->grid;
+  double *array1 = field1->ptr;
+  double *array2 = field2->ptr;
+  double missval = field1->missval;
 
-  if ( ! (gridInqXvals(gridID1, NULL) && gridInqYvals(gridID1, NULL)) )
-    cdoAbort("Source grid has no values");
+  int gridtype1 = gridInqType(gridID1);
+  int gridtype2 = gridInqType(gridID2);
 
-  lon_is_circular = gridIsCircular(gridID1);
+  int nlon1 = gridInqXsize(gridID1);
+  int nlat1 = gridInqYsize(gridID1);
 
-  nlon1 = gridInqXsize(gridID1);
-  nlat1 = gridInqYsize(gridID1);
+  int lon_is_circular = 0;
+  
+  bool lgeorefgrid = true;
+  if ( grid_is_distance_generic(gridID1) && grid_is_distance_generic(gridID2) ) lgeorefgrid = false;
 
-  array1_2D = (double **) Malloc(nlat1*sizeof(double *));
-  for ( ilat = 0; ilat < nlat1; ilat++ )
+  double **array1_2D = (double **) Malloc(nlat1*sizeof(double *));
+  for ( int ilat = 0; ilat < nlat1; ilat++ )
     array1_2D[ilat] = array1 + ilat*nlon1;
 
-  if ( lon_is_circular ) nlon1 += 1;
-  lon1 = (double*) Malloc(nlon1*sizeof(double));
-  lat1 = (double*) Malloc(nlat1*sizeof(double));
+  if ( lgeorefgrid )
+    {
+      if ( ! (gridInqXvals(gridID1, NULL) && gridInqYvals(gridID1, NULL)) )
+        cdoAbort("Source grid has no coordinate values!");
+  
+      lon_is_circular = gridIsCircular(gridID1);
+
+      if ( lon_is_circular ) nlon1 += 1;
+    }
+  
+  double *lon1 = (double*) Malloc(nlon1*sizeof(double));
+  double *lat1 = (double*) Malloc(nlat1*sizeof(double));
   gridInqXvals(gridID1, lon1);
   gridInqYvals(gridID1, lat1);
-  if ( lon_is_circular ) lon1[nlon1-1] = 0;
 
-  gridInqXunits(gridID1, units);
+  if ( lgeorefgrid )
+    {
+      if ( lon_is_circular ) lon1[nlon1-1] = 0;
 
-  grid_to_radian(units, nlon1, lon1, "grid1 center lon"); 
-  grid_to_radian(units, nlat1, lat1, "grid1 center lat"); 
+      gridInqXunits(gridID1, units);
 
-  if ( lon_is_circular ) lon1[nlon1-1] = lon1[0] + 2*M_PI;
+      grid_to_radian(units, nlon1, lon1, "grid1 center lon"); 
+      grid_to_radian(units, nlat1, lat1, "grid1 center lat"); 
 
-  nlon2 = gridInqXsize(gridID2);
-  nlat2 = gridInqYsize(gridID2);
+      if ( lon_is_circular ) lon1[nlon1-1] = lon1[0] + 2*M_PI;
+    }
+  
+  int xsize2 = gridInqXsize(gridID2);
+  int ysize2 = gridInqYsize(gridID2);
 
-  if ( nlon2 == 1 && nlat2 == 1 )
+  if ( xsize2 == 1 && ysize2 == 1 )
     {
       double lon2, lat2;
 
@@ -748,19 +751,19 @@ void intgridbil(field_t *field1, field_t *field2)
 
       gridInqXunits(gridID2, units);
 
-      grid_to_radian(units, nlon2, &lon2, "grid2 center lon"); 
-      grid_to_radian(units, nlat2, &lat2, "grid2 center lat"); 
+      grid_to_radian(units, xsize2, &lon2, "grid2 center lon"); 
+      grid_to_radian(units, ysize2, &lat2, "grid2 center lat"); 
 
       if ( lon2 < lon1[0] ) lon2 += 2*M_PI;
 
       if ( lon2 > lon1[nlon1-1] )
 	{
-	  field  = array1_2D;
+	  double **field = array1_2D;
 	  array1_2D = (double **) Malloc(nlat1*sizeof(double *));
 	  lon1 = (double*) Realloc(lon1, (nlon1+1)*sizeof(double));
-	  array = (double*) Malloc(nlat1*(nlon1+1)*sizeof(double));
+	  double *array = (double*) Malloc(nlat1*(nlon1+1)*sizeof(double));
 
-	  for ( ilat = 0; ilat < nlat1; ilat++ )
+	  for ( int ilat = 0; ilat < nlat1; ilat++ )
 	    {
 	      array1_2D[ilat] = array + ilat*(nlon1+1);  
 	      memcpy(array1_2D[ilat], field[ilat], nlon1*sizeof(double));
@@ -769,6 +772,7 @@ void intgridbil(field_t *field1, field_t *field2)
 	    }
 	  nlon1++;
 	  Free(field);
+          Free(array);
 	}
 
       if ( lon2 < lon1[0] || lon2 > lon1[nlon1-1] )
@@ -785,50 +789,71 @@ void intgridbil(field_t *field1, field_t *field2)
     }
   else
     {
-      int gridsize2;
-      double *lon2, *lat2;
-
-      if ( gridInqType(gridID2) == GRID_GME ) gridID2 = gridToUnstructured(gridID2, 0);
-
-      if ( gridInqType(gridID2) != GRID_UNSTRUCTURED && gridInqType(gridID2) != GRID_CURVILINEAR )
-	gridID2 = gridToCurvilinear(gridID2, 0);
+      if ( lgeorefgrid )
+        {
+          if ( gridInqType(gridID2) == GRID_GME ) gridID2 = gridToUnstructured(gridID2, 0);
 
-      if ( ! (gridInqXvals(gridID2, NULL) && gridInqYvals(gridID2, NULL)) )
-	cdoAbort("Target grid has no values");
+          if ( gridInqType(gridID2) != GRID_UNSTRUCTURED && gridInqType(gridID2) != GRID_CURVILINEAR )
+            gridID2 = gridToCurvilinear(gridID2, 0);
 
-      gridsize2 = gridInqSize(gridID2);
-
-      lon2 = (double*) Malloc(gridsize2*sizeof(double));
-      lat2 = (double*) Malloc(gridsize2*sizeof(double));
-      gridInqXvals(gridID2, lon2);
-      gridInqYvals(gridID2, lat2);
-
-      gridInqXunits(gridID2, units);
-
-      grid_to_radian(units, gridsize2, lon2, "grid2 center lon"); 
-      grid_to_radian(units, gridsize2, lat2, "grid2 center lat"); 
+          if ( ! (gridInqXvals(gridID2, NULL) && gridInqYvals(gridID2, NULL)) )
+            cdoAbort("Target grid has no coordinate values!");
+        }
+      
+      int gridsize2 = gridInqSize(gridID2);
+
+      double *xvals2 = (double*) Malloc(gridsize2*sizeof(double));
+      double *yvals2 = (double*) Malloc(gridsize2*sizeof(double));
+
+      if ( lgeorefgrid )
+        {
+          gridInqXvals(gridID2, xvals2);
+          gridInqYvals(gridID2, yvals2);
+
+          gridInqXunits(gridID2, units);
+          
+          grid_to_radian(units, gridsize2, xvals2, "grid2 center lon"); 
+          grid_to_radian(units, gridsize2, yvals2, "grid2 center lat"); 
+
+          for ( int i = 0; i < gridsize2; ++i )
+            {
+              if ( xvals2[i] < lon1[0]       ) xvals2[i] += 2*M_PI;
+              if ( xvals2[i] > lon1[nlon1-1] ) xvals2[i] -= 2*M_PI;
+            }
+        }
+      else
+        {
+          double *xcoord = (double*) Malloc(xsize2*sizeof(double));
+          double *ycoord = (double*) Malloc(ysize2*sizeof(double));
 
-      for ( int i = 0; i < gridsize2; ++i )
-	{
-	  if ( lon2[i] < lon1[0]       ) lon2[i] += 2*M_PI;
-	  if ( lon2[i] > lon1[nlon1-1] ) lon2[i] -= 2*M_PI;
-	}
+          gridInqXvals(gridID2, xcoord);
+          gridInqYvals(gridID2, ycoord);
+  
+          for ( int j = 0; j < ysize2; ++j )
+            for ( int i = 0; i < xsize2; ++i )
+              {
+                xvals2[j*xsize2+i] = xcoord[i]; 
+                yvals2[j*xsize2+i] = ycoord[j]; 
+              }
+  
+          Free(xcoord);
+          Free(ycoord);
+        }
 
       intlinarr2(missval, lon_is_circular, 
 		 nlon1, nlat1, array1, lon1, lat1,
-		 gridsize2, array2, lon2, lat2);
+		 gridsize2, array2, xvals2, yvals2);
 
-      nmiss = 0;
-      for ( i = 0; i < gridsize2; ++i )
+      int nmiss = 0;
+      for ( int i = 0; i < gridsize2; ++i )
 	if ( DBL_IS_EQUAL(array2[i], missval) ) nmiss++;
 
       field2->nmiss = nmiss;
 
-      Free(lon2);
-      Free(lat2);
+      Free(xvals2);
+      Free(yvals2);
     }
 
-  if (array) Free(array);
   Free(lon1);
   Free(lat1);
   Free(array1_2D);
diff --git a/src/job.c b/src/job.c
index bc851ba..d32fc97 100644
--- a/src/job.c
+++ b/src/job.c
@@ -335,14 +335,19 @@ static int drmaa_submit(const char *expname, const char *jobfilename, const char
 
 int job_submit(const char *expname, const char *jobfilename, const char *jobname, const char *tmppath, const char *ftppath)
 {
-  int status = 0;
+  int status = -1;
 #if defined(HAVE_LIBDRMAA)
 
   status = drmaa_submit(expname, jobfilename, jobname, tmppath, ftppath);
 #else
+  UNUSED(expname);
+  UNUSED(jobfilename);
+  UNUSED(jobname);
+  UNUSED(tmppath);
+  UNUSED(ftppath);
   fprintf(stderr, "DRMAA support not compiled in!\n");
 #endif
-  return (status);
+  return status;
 }
 
 
@@ -370,11 +375,14 @@ size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
 
 
 int my_progress_func(void *stdout_is_tty,
-			double t, /* dltotal */
-			double d, /* dlnow */
-			double ultotal,
-			double ulnow)
+                     double t, /* dltotal */
+                     double d, /* dlnow */
+                     double ultotal,
+                     double ulnow)
 {
+  UNUSED(ultotal);
+  UNUSED(ulnow);
+
   if ( *(char*)stdout_is_tty )
     {
       fprintf(stdout, "\b\b\b\b\b%4d%%", (int) (d*100/t));
@@ -498,10 +506,15 @@ int ftpget(int flag, const char *url, const char *path, const char *target, cons
 
   if ( flag ) fprintf(stdout, "\n");
 #else
+  UNUSED(flag);
+  UNUSED(url);
+  UNUSED(path);
+  UNUSED(target);
+  UNUSED(source);
   fprintf(stderr, "CURL support not compiled in!\n");
 #endif
 
-  return (status);
+  return status;
 }
 
 
@@ -569,10 +582,12 @@ int ftprmd(const char *url, const char *path)
   curl_global_cleanup();
 
 #else
+  UNUSED(url);
+  UNUSED(path);
   fprintf(stderr, "CURL support not compiled in!\n");
 #endif
 
-  return (status);
+  return status;
 }
 
 
diff --git a/src/juldate.c b/src/juldate.c
index 54a2154..75bccef 100644
--- a/src/juldate.c
+++ b/src/juldate.c
@@ -14,7 +14,7 @@ juldate_t juldate_encode(int calendar, int date, int time)
   encode_caldaysec(calendar, year, month, day, hour, minute, second,
 		   &juldate.julday, &juldate.secofday);
 
-  return (juldate);
+  return juldate;
 }
 
 
@@ -37,27 +37,23 @@ juldate_t juldate_sub(juldate_t juldate2, juldate_t juldate1)
   (void) julday_sub(juldate1.julday, juldate1.secofday, juldate2.julday, juldate2.secofday, 
 		    &juldate.julday, &juldate.secofday);
 
-  return (juldate);
+  return juldate;
 }
 
 
 juldate_t juldate_add_seconds(int seconds, juldate_t juldate)
 {
-  juldate_t juldate_new;
-
-  juldate_new = juldate;
+  juldate_t juldate_new = juldate;
 
   julday_add_seconds(seconds, &juldate_new.julday, &juldate_new.secofday);
 
-  return (juldate_new);
+  return juldate_new;
 }
 
 
 double juldate_to_seconds(juldate_t juldate)
 {
-  double seconds;
-
-  seconds = juldate.julday*86400. + juldate.secofday;
+  double seconds = juldate.julday*86400. + juldate.secofday;
 
-  return (seconds);
+  return seconds;
 }
diff --git a/src/kdtreelib/kdtree_cartesian.c b/src/kdtreelib/kdtree_cartesian.c
index 11a2be7..6b21877 100644
--- a/src/kdtreelib/kdtree_cartesian.c
+++ b/src/kdtreelib/kdtree_cartesian.c
@@ -241,53 +241,53 @@ kd_doOrtRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max,
 struct kdNode *
 kd_nearest(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq, int dim)
 {
-    struct kdNode *nearer, *further, *nearest = NULL, *tmp, *tmp_nearest;
-    kdata_t dist_sq, tmp_dist_sq, dx;
+    if ( !node ) return NULL;
 
-    if (!node)
-        return NULL;
-
-    if (p[node->split] < node->location[node->split]) {
-        nearer = node->left;
+    struct kdNode *nearer, *further;
+    if ( p[node->split] < node->location[node->split] ) {
+        nearer  = node->left;
         further = node->right;
     } else {
-        nearer = node->right;
+        nearer  = node->right;
         further = node->left;
     }
-    tmp = kd_nearest(nearer, p, max_dist_sq, dim);
-    if (tmp)
+    
+    struct kdNode *tmp = kd_nearest(nearer, p, max_dist_sq, dim);
+    struct kdNode *nearest = NULL;
+    if ( tmp )
         nearest = tmp;
     else
         nearest = node;
 
-    dist_sq = kd_dist_sq(nearest->location, p, dim);
+    kdata_t dist_sq = kd_dist_sq(nearest->location, p, dim);
     if (*max_dist_sq > dist_sq)
 	*max_dist_sq = dist_sq;
 
     if (!further)
         return nearest;
 
-    dx = kd_min(KDATA_ABS(p[node->split] - further->min[node->split]),
-                KDATA_ABS(p[node->split] - further->max[node->split]));
-    if (*max_dist_sq > kd_sqr(dx)) {
+    kdata_t dx = kd_min(KDATA_ABS(p[node->split] - further->min[node->split]),
+                        KDATA_ABS(p[node->split] - further->max[node->split]));
+    if ( *max_dist_sq > kd_sqr(dx) ) {
         /*
          * some part of the further hyper-rectangle is in the search
          * radius, search the further node 
          */
+        struct kdNode *tmp_nearest;
         tmp = kd_nearest(further, p, max_dist_sq, dim);
-        if (tmp)
+        if ( tmp )
             tmp_nearest = tmp;
         else
             tmp_nearest = further;
 
-        tmp_dist_sq = kd_dist_sq(tmp_nearest->location, p, dim);
-        if (tmp_dist_sq < dist_sq) {
+        kdata_t tmp_dist_sq = kd_dist_sq(tmp_nearest->location, p, dim);
+        if ( tmp_dist_sq < dist_sq ) {
             nearest = tmp_nearest;
             dist_sq = tmp_dist_sq;
             *max_dist_sq = kd_min(dist_sq, *max_dist_sq);
         }
         // Uwe Schulzweida
-        else if (tmp_dist_sq <= dist_sq && tmp_nearest->index < nearest->index) {
+        else if ( tmp_dist_sq <= dist_sq && tmp_nearest->index < nearest->index ) {
             nearest = tmp_nearest;
             dist_sq = tmp_dist_sq;
             *max_dist_sq = kd_min(dist_sq, *max_dist_sq);
@@ -317,19 +317,16 @@ struct pqueue *
 kd_qnearest(struct kdNode *node, kdata_t *p,
             kdata_t *max_dist_sq, unsigned int q, int dim)
 {
-    struct pqueue *res;
-    uint32_t i;
-
-    if ((res = pqinit(NULL, q + 2)) == NULL)
-        return NULL;
-    if (!kd_doQnearest(node, p, max_dist_sq, q + 1, dim, res)) {
-        for(i = 0; i < res->size; i++) {
-            free(res->d[i]);
-        }
+    struct pqueue *res = pqinit(NULL, q + 2);
+    if ( res == NULL) return NULL;
+    
+    if ( !kd_doQnearest(node, p, max_dist_sq, q + 1, dim, res) ) {
+        for ( uint32_t i = 0; i < res->size; ++i ) free(res->d[i]);
         free(res->d);
         free(res);
         return NULL;
     }
+    
     return res;
 }
 
@@ -347,33 +344,20 @@ static int
 kd_check_dist(struct kdNode *node, kdata_t *p,
               kdata_t *max_dist_sq, unsigned int q, int dim, struct pqueue *res)
 {
-    struct resItem *point, *item;
-    kdata_t dist_sq;
-
-    dist_sq = kd_dist_sq(node->location, p, dim);
-    if (dist_sq < *max_dist_sq && kd_isleaf(node)) {
-        if ((point = (struct resItem *) kd_malloc(sizeof(struct resItem), "kd_doQnearest: "))
-            == NULL)
-            return 0;
+    kdata_t dist_sq = kd_dist_sq(node->location, p, dim);
+    if ( dist_sq < *max_dist_sq && kd_isleaf(node) ) {
+        struct resItem *point = (struct resItem *) kd_malloc(sizeof(struct resItem), "kd_doQnearest: ");
+        if ( point == NULL) return 0;
         point->node = node;
         point->dist_sq = dist_sq;
         pqinsert(res, point);
     }
-    /*
-    else if (res->size > 1 && dist_sq <= *max_dist_sq && kd_isleaf(node)) {
-        pqpeek_max(res, &item);
-        if ( node->index < item->node->index )
-          {
-            item->node = node;
-            item->dist_sq = dist_sq;
-          }
-    }
-    */
 
-    if (res->size > q) {
+    if ( res->size > q ) {
+        struct resItem *item;
         pqremove_max(res, &item);
         free(item);
-        if (res->size > 1) {
+        if ( res->size > 1 ) {
             /*
              * Only inspect the queue if there are items left 
              */
@@ -394,27 +378,26 @@ int
 kd_doQnearest(struct kdNode *node, kdata_t *p,
               kdata_t *max_dist_sq, unsigned int q, int dim, struct pqueue *res)
 {
-    struct kdNode *nearer, *further;
-    kdata_t dx;
+    if ( !node ) return 1;
 
-    if (!node) return 1;
+    if ( !kd_check_dist(node, p, max_dist_sq, q, dim, res) ) return 0;
 
-    if (!kd_check_dist(node, p, max_dist_sq, q, dim, res)) return 0;
-
-    if (p[node->split] < node->location[node->split]) {
-        nearer = node->left;
+    struct kdNode *nearer, *further;
+    if ( p[node->split] < node->location[node->split] ) {
+        nearer  = node->left;
         further = node->right;
     } else {
-        nearer = node->right;
+        nearer  = node->right;
         further = node->left;
     }
-    if (!kd_doQnearest(nearer, p, max_dist_sq, q, dim, res)) return 0;
+    if ( !kd_doQnearest(nearer, p, max_dist_sq, q, dim, res) ) return 0;
 
-    if (!further) return 1;
+    if ( !further ) return 1;
 
-    dx = kd_min(KDATA_ABS(p[node->split] - further->min[node->split]),
-                KDATA_ABS(p[node->split] - further->max[node->split]));
-    if (*max_dist_sq > kd_sqr(dx)) {
+    kdata_t dx = kd_min(KDATA_ABS(p[node->split] - further->min[node->split]),
+                        KDATA_ABS(p[node->split] - further->max[node->split]));
+    
+    if ( *max_dist_sq > kd_sqr(dx) ) {
         /*
          * some part of the further hyper-rectangle is in the search
          * radius, search the further node 
@@ -447,13 +430,11 @@ struct pqueue *
 kd_range(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
          int dim, int ordered)
 {
-    struct pqueue *res;
-    uint32_t i;
-
-    if ((res = pqinit(NULL, 1)) == NULL)
-        return NULL;
-    if (!kd_doRange(node, p, max_dist_sq, dim, res, ordered)) {
-        for(i = 0; i < res->size; i++) {
+    struct pqueue *res = pqinit(NULL, 1);
+    if ( res == NULL ) return NULL;
+    
+    if ( !kd_doRange(node, p, max_dist_sq, dim, res, ordered) ) {
+        for( uint32_t i = 0; i < res->size; ++i ) {
             free(res->d[i]);
         }
         free(res->d);
diff --git a/src/merge_sort2.c b/src/merge_sort2.c
index 9dfce43..91770e4 100644
--- a/src/merge_sort2.c
+++ b/src/merge_sort2.c
@@ -68,7 +68,7 @@ void sort_par(long num_links, double *restrict add1, int parent, int par_depth)
   if ( nsplit != 2 )
     {
       cdoAbort("Error: splitting into more than two subsegments not allowed\n"
-	     "       in this implementation of merge sort\n");
+	     "       in this implementation of merge sort!");
     }
 
   idx = (long*) Malloc(num_links*sizeof(long));
@@ -88,7 +88,7 @@ void sort_par(long num_links, double *restrict add1, int parent, int par_depth)
       omp_set_nested(1);            
       if ( omp_get_nested() == 0 )
 	cdoWarning("openMP implementation seems to not support nested parallelism.\n"
-	       "Maximum of CPUs used is 2 instead of %i.\n", omp_get_num_threads());
+	       "\tMaximum of CPUs used is 2 instead of %i.\n", omp_get_num_threads());
     }                                    
 #endif
 
@@ -104,7 +104,7 @@ void sort_par(long num_links, double *restrict add1, int parent, int par_depth)
 
 #if defined(_OPENMP)
       /*      if ( 0 )
-      	cdoPrint("I am %i (parent %i), my_depth is: %i thread_num %i (%i) \n",
+      	cdoPrint("I am %i (parent %i), my_depth is: %i thread_num %i (%i)",
 	who_am_i,parent,my_depth,omp_get_thread_num()+1,omp_get_num_threads());
       */
 #endif
@@ -221,7 +221,7 @@ void sort_add(long num_links, double *restrict add1)
 	}
 
       if ( i == num_links ) {
-	cdoAbort("Internal problem; link 1 not found!\n");
+	cdoAbort("Internal problem; link 1 not found!");
 	exit(1);
       }
     }
@@ -284,7 +284,7 @@ void sort_add(long num_links, double *restrict add1)
 	}
 
       if ( i == num_links ) {
-	cdoAbort("Internal problem; link 2 not found!\n");
+	cdoAbort("Internal problem; link 2 not found!");
       }
     }
 
diff --git a/src/modules.c b/src/modules.c
index 861bcf5..7421315 100644
--- a/src/modules.c
+++ b/src/modules.c
@@ -114,6 +114,7 @@ void *Invertlev(void *argument);
 void *Isosurface(void *argument);
 void *Kvl(void *argument);
 void *Log(void *argument);
+void *MapReduce(void *argument);
 void *Maskbox(void *argument);
 void *Mastrfu(void *argument);
 void *Math(void *argument);
@@ -162,7 +163,7 @@ void *Settime(void *argument);
 void *Setzaxis(void *argument);
 void *Showinfo(void *argument);
 void *Sinfo(void *argument);
-void *Smooth9(void *argument);
+void *Smooth(void *argument);
 void *Sort(void *argument);
 void *Sorttimestamp(void *argument);
 void *Specinfo(void *argument);
@@ -173,7 +174,6 @@ void *Splitrec(void *argument);
 void *Splitsel(void *argument);
 void *Splittime(void *argument);
 void *Splityear(void *argument);
-void *SSOpar(void *argument);
 void *Subtrend(void *argument);
 void *Tee(void *argument);
 void *Template1(void *argument);
@@ -318,7 +318,7 @@ void *Maggraph(void *argument);
 #define  EOF3dOperators         {"eof3d","eof3dspatial","eof3dtime"}
 #define  ExprOperators          {"expr", "exprf", "aexpr", "aexprf"}
 #define  FCOperators            {"fc2sp", "sp2fc", "fc2gp", "gp2fc"}
-#define  FiledesOperators       {"filedes", "griddes", "griddes2", "zaxisdes", "vct", "vct2", "pardes", \
+#define  FiledesOperators       {"filedes", "griddes", "griddes2", "zaxisdes", "vct", "vct2", "codetab", \
                                  "vlist", "partab", "partab2", "spartab"}
 #define  FillmissOperators      {"fillmiss", "fillmiss2"}
 #define  FilterOperators        {"bandpass", "highpass", "lowpass"}
@@ -352,6 +352,7 @@ void *Maggraph(void *argument);
 #define  IsosurfaceOperators    {"isosurface"}
 #define  KvlOperators           {"read_cmor_table", "conv_cmor_table"}
 #define  LogOperators           {"dumplogs", "daylogs", "monlogs", "dumplogo", "snamelogo", "scalllogo", "smemlogo", "stimelogo", "sperclogo"}
+#define  MapReduceOperators     {"reducegrid"}
 #define  MaskboxOperators       {"masklonlatbox", "maskindexbox"}
 #define  MaskregionOperators    {"maskregion"}
 #define  MastrfuOperators       {"mastrfu"}
@@ -364,7 +365,7 @@ void *Maggraph(void *argument);
 #define  MonarithOperators      {"monadd", "monsub", "monmul", "mondiv"}
 #define  MrotuvOperators        {"mrotuv"}
 #define  MrotuvbOperators       {"mrotuvb"}
-#define  NinfoOperators         {"nyear", "nmon", "ndate", "ntime", "ncode", "npar", "nlevel"}
+#define  NinfoOperators         {"nyear", "nmon", "ndate", "ntime", "ncode", "npar", "nlevel", "ngridpoints", "ngrids"}
 #define  NmltestOperators       {"nmltest"}
 #define  OutputOperators        {"output", "outputint", "outputsrv", "outputext", "outputf", "outputts", \
                                  "outputfld", "outputarr", "outputxyz"}
@@ -411,16 +412,16 @@ void *Maggraph(void *argument);
 #define  SethaloOperators       {"sethalo", "tpnhalo"}
 #define  SetmissOperators       {"setmissval", "setctomiss", "setmisstoc", "setrtomiss", "setvrange"}
 #define  SetmisstonnOperators   {"setmisstonn", "setmisstodis"}
-#define  Setpartab0Operators    {"setpartab"}
+#define  SetcodetabOperators    {"setcodetab"}
 #define  SetpartabOperators     {"setpartabc", "setpartabp", "setpartabn"}
 #define  SetrcanameOperators    {"setrcaname"}
 #define  SettimeOperators       {"setyear", "setmon", "setday", "setdate", "settime", "settunits", \
-                                 "settaxis", "setreftime", "setcalendar", "shifttime"}
+                                 "settaxis", "settbounds", "setreftime", "setcalendar", "shifttime"}
 #define  SetzaxisOperators      {"setzaxis", "genlevelbounds"}
 #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"}
-#define  Smooth9Operators       {"smooth9"}
+#define  SmoothOperators        {"smooth", "smooth9"}
 #define  SortOperators          {"sortcode", "sortparam", "sortname", "sortlevel"}
 #define  SorttimestampOperators {"sorttimestamp", "sorttaxis"}
 #define  SpecinfoOperators      {"specinfo"}
@@ -431,7 +432,6 @@ void *Maggraph(void *argument);
 #define  SplitselOperators      {"splitsel"}
 #define  SplittimeOperators     {"splithour", "splitday", "splitmon", "splitseas"}
 #define  SplityearOperators     {"splityear", "splityearmon"}
-#define  SSOparOperators        {"ssopar"}
 #define  SubtrendOperators      {"subtrend"}
 #define  TeeOperators           {"tee"}
 #define  Template1Operators     {"template1"}
@@ -474,11 +474,11 @@ void *Maggraph(void *argument);
 #define  VargenOperators        {"random", "const", "sincos", "coshill", "for", "topo", "temp", "mask", "stdatm"}
 #define  VarrmsOperators        {"varrms"}
 #define  VertintmlOperators     {"ml2pl", "ml2hl", "ml2plx", "ml2hlx", "ml2pl_lp", "ml2hl_lp", "ml2plx_lp", "ml2hlx_lp"}
-#define  VertintapOperators     {"ap2pl", "ap2plx", "ap2pl_lp", "ap2plx_lp"}
+#define  VertintapOperators     {"ap2pl", "ap2plx", "ap2pl_lp", "ap2plx_lp", "ap2hl", "ap2hlx"}
 #define  VertstatOperators      {"vertmin", "vertmax", "vertsum", "vertint", "vertmean", "vertavg", "vertstd", "vertstd1", "vertvar", "vertvar1"}
 #define  VertcumOperators       {"vertcum", "vertcumhl"}
 #define  VertwindOperators      {"vertwind"}
-#define  VerifygridOperators    {"verifygrid", "verifygridtest"}
+#define  VerifygridOperators    {"verifygrid"}
 #define  WindOperators          {"uv2dv", "uv2dvl", "dv2uv", "dv2uvl", "dv2ps"}
 #define  WritegridOperators     {"writegrid"}
 #define  WriterandomOperators   {"writerandom"}
@@ -636,6 +636,7 @@ static modules_t Modules[] =
   { Isosurface,     NULL,              IsosurfaceOperators,    1,   CDI_REAL,  1,  1 },
   { Kvl,            NULL,              KvlOperators,           1,   CDI_REAL,  0,  0 },
   { Log,            NULL,              LogOperators,           0,   CDI_REAL,  1,  0 },
+  { MapReduce,      MapReduceHelp,     MapReduceOperators,     1,   CDI_REAL,  1,  1 },
   { Maskbox,        MaskboxHelp,       MaskboxOperators,       1,   CDI_REAL,  1,  1 },
   { Maskbox,        MaskregionHelp,    MaskregionOperators,    1,   CDI_REAL,  1,  1 },
   { Mastrfu,        MastrfuHelp,       MastrfuOperators,       1,   CDI_REAL,  1,  1 },
@@ -690,14 +691,14 @@ static modules_t Modules[] =
   { Sethalo,        SethaloHelp,       SethaloOperators,       1,   CDI_REAL,  1,  1 },
   { Setmiss,        SetmissHelp,       SetmissOperators,       1,   CDI_REAL,  1,  1 },
   { Fillmiss,       SetmissHelp,       SetmisstonnOperators,   1,   CDI_REAL,  1,  1 },
-  { Setpartab,      SetHelp,           Setpartab0Operators,    1,   CDI_REAL,  1,  1 },
+  { Setpartab,      SetHelp,           SetcodetabOperators,    1,   CDI_REAL,  1,  1 },
   { Setpartab,      SetpartabHelp,     SetpartabOperators,     1,   CDI_REAL,  1,  1 },
   { Setrcaname,     NULL,              SetrcanameOperators,    1,   CDI_REAL,  1,  1 },
   { Settime,        SettimeHelp,       SettimeOperators,       1,   CDI_BOTH,  1,  1 },
   { Setzaxis,       SetzaxisHelp,      SetzaxisOperators,      1,   CDI_BOTH,  1,  1 },
   { Showinfo,       ShowinfoHelp,      ShowinfoOperators,      1,   CDI_BOTH,  1,  0 },
   { Sinfo,          SinfoHelp,         SinfoOperators,         1,   CDI_BOTH, -1,  0 },
-  { Smooth9,        Smooth9Help,       Smooth9Operators,       1,   CDI_REAL,  1,  1 },
+  { Smooth,         SmoothHelp,        SmoothOperators,        1,   CDI_REAL,  1,  1 },
   { Sort,           NULL,              SortOperators,          1,   CDI_REAL,  1,  1 },
   { Sorttimestamp,  NULL,              SorttimestampOperators, 1,   CDI_REAL, -1,  1 },
   { Specinfo,       NULL,              SpecinfoOperators,      1,   CDI_REAL,  0,  0 },
@@ -708,7 +709,6 @@ static modules_t Modules[] =
   { Splitsel,       SplitselHelp,      SplitselOperators,      1,   CDI_BOTH,  1, -1 },
   { Splittime,      SplittimeHelp,     SplittimeOperators,     1,   CDI_BOTH,  1, -1 },
   { Splityear,      SplittimeHelp,     SplityearOperators,     1,   CDI_BOTH,  1, -1 },
-  { SSOpar,         NULL,              SSOparOperators,        0,   CDI_REAL,  1,  1 },
   { Subtrend,       SubtrendHelp,      SubtrendOperators,      1,   CDI_REAL,  3,  1 },
   { Tee,            NULL,              TeeOperators,           1,   CDI_REAL,  2,  1 },
   { Template1,      NULL,              Template1Operators,     0,   CDI_REAL,  1,  1 },
@@ -848,7 +848,8 @@ static const char *opalias[][2] =
   {"ncode",               "npar"},
   {"nvar",                "npar"},
   {"outputkey",           "outputtab"},
-  {"vardes",              "pardes"},
+  {"vardes",              "codetab"},
+  {"pardes",              "codetab"},
   {"selvar",              "selname"},
   {"delvar",              "delname"},
   {"remapcon1",           "remaplaf"},
@@ -858,6 +859,7 @@ static const char *opalias[][2] =
   {"selgridname",         "selgrid"},
   {"setvar",              "setname"},
   {"setpartabv",          "setpartabn"},
+  {"setpartab",           "setcodetab"},
   {"sinfov",              "sinfon"},
   {"sortvar",             "sortname"},
   {"splitvar",            "splitname"},
diff --git a/src/namelist.c b/src/namelist.c
index 9f10466..f6f35fd 100644
--- a/src/namelist.c
+++ b/src/namelist.c
@@ -297,10 +297,14 @@ void getnite(FILE *nmlfp, namelist_t *nml)
 	    }
         }
 
+    LABEL_READLINE:
+
       if ( ! readline(nmlfp, nml->line.lineac, MAX_LINE_LEN) ) break;
 
       linelen = strlen(nml->line.lineac);
 
+      if ( linelen == 0 || nml->line.lineac[0] == '#' || nml->line.lineac[0] == '!' ) goto LABEL_READLINE; 
+
       for ( i = 0; i < linelen+1; i++ )
 	{
 	  nml->line.linelc[i] = tolower(nml->line.lineac[i]);
diff --git a/src/operator_help.h b/src/operator_help.h
index f509516..747de79 100644
--- a/src/operator_help.h
+++ b/src/operator_help.h
@@ -95,7 +95,7 @@ static const char *DiffHelp[] = {
 
 static const char *NinfoHelp[] = {
     "NAME",
-    "    npar, nlevel, nyear, nmon, ndate, ntime - ",
+    "    npar, nlevel, nyear, nmon, ndate, ntime, ngridpoints, ngrids - ",
     "    Print the number of parameters, levels or times",
     "",
     "SYNOPSIS",
@@ -106,18 +106,22 @@ static const char *NinfoHelp[] = {
     "    input dataset.",
     "",
     "OPERATORS",
-    "    npar    Number of parameters",
-    "            Prints the number of parameters (variables).",
-    "    nlevel  Number of levels",
-    "            Prints the number of levels for each variable.",
-    "    nyear   Number of years",
-    "            Prints the number of different years.",
-    "    nmon    Number of months",
-    "            Prints the number of different combinations of years and months.",
-    "    ndate   Number of dates",
-    "            Prints the number of different dates.",
-    "    ntime   Number of timesteps",
-    "            Prints the number of timesteps.",
+    "    npar         Number of parameters",
+    "                 Prints the number of parameters (variables).",
+    "    nlevel       Number of levels",
+    "                 Prints the number of levels for each variable.",
+    "    nyear        Number of years",
+    "                 Prints the number of different years.",
+    "    nmon         Number of months",
+    "                 Prints the number of different combinations of years and months.",
+    "    ndate        Number of dates",
+    "                 Prints the number of different dates.",
+    "    ntime        Number of timesteps",
+    "                 Prints the number of timesteps.",
+    "    ngridpoints  Number of gridpoints",
+    "                 Prints the number of gridpoints for each variable.",
+    "    ngrids       Number of horizontal grids",
+    "                 Prints the number of horizontal grids.",
     NULL
 };
 
@@ -160,18 +164,20 @@ static const char *ShowinfoHelp[] = {
 
 static const char *FiledesHelp[] = {
     "NAME",
-    "    pardes, griddes, zaxisdes, vct - Dataset description",
+    "    partab, codetab, griddes, zaxisdes, vct - Dataset description",
     "",
     "SYNOPSIS",
     "    <operator>  ifile",
     "",
     "DESCRIPTION",
-    "    This module prints the description of the parameters, the grids,",
-    "    the z-axis or the vertical coordinate table.",
+    "    This module provides operators to print meta information about a dataset.",
+    "    The printed meta-data depends on the chosen operator.",
     "",
     "OPERATORS",
-    "    pardes    Parameter description",
-    "              Prints a table with a description of all variables.",
+    "    partab    Parameter table",
+    "              Prints all available meta information of the variables.",
+    "    codetab   Parameter code table",
+    "              Prints a code table with a description of all variables.",
     "              For each variable the operator prints one line listing the",
     "              code, name, description and units.",
     "    griddes   Grid description",
@@ -277,6 +283,10 @@ static const char *MergeHelp[] = {
     "ENVIRONMENT",
     "    SKIP_SAME_TIME",
     "        If set to 1, skips all consecutive timesteps with a double entry of the same timestamp.",
+    "",
+    "NOTE",
+    "    The operators in this module need to open all input files simultaneously.",
+    "    The maximum number of open files depends on the operating system!",
     NULL
 };
 
@@ -326,6 +336,10 @@ static const char *SplitHelp[] = {
     "        Set the default file suffix. This suffix will be added to the output file ",
     "        names instead of the filename extension derived from the file format. ",
     "        Set this variable to NULL to disable the adding of a file suffix.",
+    "",
+    "NOTE",
+    "    The operators in this module need to open all output files simultaneously.",
+    "    The maximum number of open files depends on the operating system!",
     NULL
 };
 
@@ -371,6 +385,10 @@ static const char *SplittimeHelp[] = {
     "        Set the default file suffix. This suffix will be added to the output file ",
     "        names instead of the filename extension derived from the file format. ",
     "        Set this variable to NULL to disable the adding of a file suffix.",
+    "",
+    "NOTE",
+    "    The operators in this module need to open all output files simultaneously.",
+    "    The maximum number of open files depends on the operating system!",
     NULL
 };
 
@@ -436,7 +454,7 @@ static const char *CollgridHelp[] = {
     "    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 structured longitude/latitude grid box.",
-    "    The parameter nx needs to be specified only non regular lon/lat grids.",
+    "    The parameter nx needs to be specified only for non regular lon/lat grids.",
     "",
     "PARAMETER",
     "    nx     INTEGER  Number of regions in x direction [default: number of input files]",
@@ -460,7 +478,7 @@ static const char *SelectHelp[] = {
     "    ifiles is an arbitrary number of input files. All input files need to have ",
     "    the same structure with the same variables on different timesteps.",
     "    The fields selected depends on the chosen parameters. Parameter is a comma",
-    "    separated list of key-value pairs. Wildcards can be used for string parameter.",
+    "    separated list of \"key=value\" pairs. Wildcards can be used for string parameter.",
     "",
     "OPERATORS",
     "    select  Select fields",
@@ -726,6 +744,25 @@ static const char *CondcHelp[] = {
     NULL
 };
 
+static const char *MapReduceHelp[] = {
+    "NAME",
+    "    reducegrid - Reduce fields to user-defined mask",
+    "",
+    "SYNOPSIS",
+    "    reducegrid,mask[,limitCoordsOutput]  ifile ofile",
+    "",
+    "DESCRIPTION",
+    "    This module holds an operator for data reduction based on a user defined mask.",
+    "    The output grid is unstructured and includes coordinate bounds. Bounds can be",
+    "    avoided by using the additional 'nobounds' keyword. With 'nocoords' given,",
+    "    coordinates a completely suppressed.",
+    "",
+    "PARAMETER",
+    "    mask               STRING file which holds the mask field",
+    "    limitCoordsOutput  STRING optional parameter to limit coordinates output: 'nobounds' disables coordinate bounds, 'nocoords' avoids all coordinate information",
+    NULL
+};
+
 static const char *CompHelp[] = {
     "NAME",
     "    eq, ne, le, lt, ge, gt - Comparison of two fields",
@@ -864,11 +901,11 @@ static const char *SetpartabHelp[] = {
 
 static const char *SetHelp[] = {
     "NAME",
-    "    setpartab, setcode, setparam, setname, setunit, setlevel, setltype - ",
+    "    setcodetab, setcode, setparam, setname, setunit, setlevel, setltype - ",
     "    Set field info",
     "",
     "SYNOPSIS",
-    "    setpartab,table  ifile ofile",
+    "    setcodetab,table  ifile ofile",
     "    setcode,code  ifile ofile",
     "    setparam,param  ifile ofile",
     "    setname,name  ifile ofile",
@@ -881,20 +918,20 @@ static const char *SetHelp[] = {
     "    parameter table, code number, parameter identifier, variable name or level is set.",
     "",
     "OPERATORS",
-    "    setpartab  Set parameter table",
-    "               Sets the parameter table for all variables.",
-    "    setcode    Set code number",
-    "               Sets the code number for all variables to the same given value.",
-    "    setparam   Set parameter identifier",
-    "               Sets the parameter identifier of the first variable.",
-    "    setname    Set variable name",
-    "               Sets the name of the first variable.",
-    "    setunit    Set variable unit",
-    "               Sets the unit of the first variable.",
-    "    setlevel   Set level",
-    "               Sets the first level of all variables.",
-    "    setltype   Set GRIB level type",
-    "               Sets the GRIB level type of all variables.",
+    "    setcodetab  Set parameter code table",
+    "                Sets the parameter code table for all variables.",
+    "    setcode     Set code number",
+    "                Sets the code number for all variables to the same given value.",
+    "    setparam    Set parameter identifier",
+    "                Sets the parameter identifier of the first variable.",
+    "    setname     Set variable name",
+    "                Sets the name of the first variable.",
+    "    setunit     Set variable unit",
+    "                Sets the unit of the first variable.",
+    "    setlevel    Set level",
+    "                Sets the first level of all variables.",
+    "    setltype    Set GRIB level type",
+    "                Sets the GRIB level type of all variables.",
     "",
     "PARAMETER",
     "    table  STRING   Parameter table file or name",
@@ -908,8 +945,8 @@ static const char *SetHelp[] = {
 
 static const char *SettimeHelp[] = {
     "NAME",
-    "    setdate, settime, setday, setmon, setyear, settunits, settaxis, setreftime, ",
-    "    setcalendar, shifttime - Set time",
+    "    setdate, settime, setday, setmon, setyear, settunits, settaxis, settbounds, ",
+    "    setreftime, setcalendar, shifttime - Set time",
     "",
     "SYNOPSIS",
     "    setdate,date  ifile ofile",
@@ -919,6 +956,7 @@ static const char *SettimeHelp[] = {
     "    setyear,year  ifile ofile",
     "    settunits,units  ifile ofile",
     "    settaxis,date,time[,inc]  ifile ofile",
+    "    settbounds,frequency  ifile ofile",
     "    setreftime,date,time[,units]  ifile ofile",
     "    setcalendar,calendar  ifile ofile",
     "    shifttime,sval  ifile ofile",
@@ -942,6 +980,8 @@ static const char *SettimeHelp[] = {
     "                 Sets the base units of a relative time axis.",
     "    settaxis     Set time axis",
     "                 Sets the time axis.",
+    "    settbounds   Set time bounds",
+    "                 Sets the time bounds.",
     "    setreftime   Set reference time",
     "                 Sets the reference time of a relative time axis.",
     "    setcalendar  Set calendar",
@@ -950,15 +990,16 @@ static const char *SettimeHelp[] = {
     "                 Shifts all timesteps by the parameter sval.",
     "",
     "PARAMETER",
-    "    day       INTEGER  Value of the new day",
-    "    month     INTEGER  Value of the new month",
-    "    year      INTEGER  Value of the new year",
-    "    units     STRING   Base units of the time axis (seconds, minutes, hours, days, months, years)",
-    "    date      STRING   Date (format: YYYY-MM-DD)",
-    "    time      STRING   Time (format: hh:mm:ss)",
-    "    inc       STRING   Optional increment (seconds, minutes, hours, days, months, years) [default: 1hour]",
-    "    calendar  STRING   Calendar (standard, proleptic_gregorian, 360_day, 365_day, 366_day)",
-    "    sval      STRING   Shift value (e.g. -3hour)",
+    "    day        INTEGER  Value of the new day",
+    "    month      INTEGER  Value of the new month",
+    "    year       INTEGER  Value of the new year",
+    "    units      STRING   Base units of the time axis (seconds, minutes, hours, days, months, years)",
+    "    date       STRING   Date (format: YYYY-MM-DD)",
+    "    time       STRING   Time (format: hh:mm:ss)",
+    "    inc        STRING   Optional increment (seconds, minutes, hours, days, months, years) [default: 1hour]",
+    "    frequency  STRING   Frequency of the time series (day, month, year)",
+    "    calendar   STRING   Calendar (standard, proleptic_gregorian, 360_day, 365_day, 366_day)",
+    "    sval       STRING   Shift value (e.g. -3hour)",
     NULL
 };
 
@@ -1341,7 +1382,7 @@ static const char *ExprHelp[] = {
     "    sqr(x)  "    "    Square of x",
     "    sqrt(x) "    "    Square Root of x",
     "    exp(x)  "    "    Exponential of x",
-    "    log(x)  "    "    Natural logarithm of x",
+    "    ln(x)   "    "    Natural logarithm of x",
     "    log10(x)"    "    Base 10 logarithm of x",
     "    sin(x)  "    "    Sine of x, where x is specified in radians",
     "    cos(x)  "    "    Cosine of x, where x is specified in radians",
@@ -1738,6 +1779,10 @@ static const char *EnsstatHelp[] = {
     "",
     "PARAMETER",
     "    p  FLOAT  Percentile number in {0, ..., 100}",
+    "",
+    "NOTE",
+    "    This operator needs to open all input files simultaneously.",
+    "    The maximum number of open files depends on the operating system!",
     NULL
 };
 
@@ -3865,19 +3910,35 @@ static const char *VertintmlHelp[] = {
 
 static const char *VertintapHelp[] = {
     "NAME",
-    "    ap2pl - Vertical interpolation",
+    "    ap2pl, ap2hl - Vertical interpolation",
     "",
     "SYNOPSIS",
     "    ap2pl,plevels  ifile ofile",
+    "    ap2hl,hlevels  ifile ofile",
     "",
     "DESCRIPTION",
-    "    Interpolate 3D variables on hybrid sigma height coordinates to pressure levels.",
+    "    Interpolate 3D variables on hybrid sigma height coordinates to pressure or height levels.",
     "    The input file must contain the 3D air pressure. The air pressure is identified",
     "    by the NetCDF CF standard name air_pressure.",
-    "    This operator requires all variables on the same horizontal grid.",
+    "    Use the alias  ap2plx/ap2hlx or the environment variable EXTRAPOLATE",
+    "    to extrapolate missing values. This operator requires all variables on the same horizontal grid.",
+    "",
+    "OPERATORS",
+    "    ap2pl  Air pressure to pressure level interpolation",
+    "           Interpolates 3D variables on hybrid sigma height coordinates to pressure level.",
+    "    ap2hl  Air pressure to height level interpolation",
+    "           Interpolates 3D variables on hybrid sigma height coordinates to height level.",
+    "           The procedure is the same as for the operator ap2pl except for",
+    "           the pressure levels being calculated from the heights by:",
+    "           plevel = 101325*exp(hlevel/-7000)",
     "",
     "PARAMETER",
     "    plevels  FLOAT  Pressure levels in pascal",
+    "    hlevels  FLOAT  Height levels in meter (max level: 65535 m)",
+    "",
+    "ENVIRONMENT",
+    "    EXTRAPOLATE",
+    "        If set to 1 extrapolate missing values.",
     "",
     "NOTE",
     "    This is a specific implementation for NetCDF files from the ICON model, it may not work with data from other sources.",
@@ -3969,6 +4030,10 @@ static const char *IntyearHelp[] = {
     "        Set the default file suffix. This suffix will be added to the output file ",
     "        names instead of the filename extension derived from the file format. ",
     "        Set this variable to NULL to disable the adding of a file suffix.",
+    "",
+    "NOTE",
+    "    This operator needs to open all output files simultaneously.",
+    "    The maximum number of open files depends on the operating system!",
     NULL
 };
 
@@ -4027,7 +4092,7 @@ static const char *WindHelp[] = {
     "DESCRIPTION",
     "    This module converts relative divergence and vorticity to U and V wind and vice versa.",
     "    Divergence and vorticity are spherical harmonic coefficients in spectral space and",
-    "    U and V are on a regular Gaussian grid. The Gaussian latitudes needs to be ordered from",
+    "    U and V are on a regular Gaussian grid. The Gaussian latitudes need to be ordered from",
     "    north to south.",
     "",
     "OPERATORS",
@@ -4172,7 +4237,7 @@ static const char *InputHelp[] = {
     "    input, inputsrv, inputext - Formatted input",
     "",
     "SYNOPSIS",
-    "    input,grid  ofile",
+    "    input,grid[,zaxis]  ofile",
     "    inputsrv  ofile",
     "    inputext  ofile",
     "",
@@ -4198,7 +4263,8 @@ static const char *InputHelp[] = {
     "              the outputext operator.",
     "",
     "PARAMETER",
-    "    grid  STRING  Grid description file or name",
+    "    grid   STRING  Grid description file or name",
+    "    zaxis  STRING  Z-axis description file",
     NULL
 };
 
@@ -4496,24 +4562,45 @@ static const char *GridcellHelp[] = {
     NULL
 };
 
-static const char *Smooth9Help[] = {
+static const char *SmoothHelp[] = {
     "NAME",
-    "    smooth9 - 9 point smoothing",
+    "    smooth, smooth9 - Smooth grid points",
     "",
     "SYNOPSIS",
+    "    smooth[,options]  ifile ofile",
     "    smooth9  ifile ofile",
     "",
     "DESCRIPTION",
-    "    Performs a 9 point smoothing on all fields with a quadrilateral curvilinear grid.",
-    "    The result at each grid point is a weighted average of the grid point plus",
-    "    the 8 surrounding points. The center point receives a weight of 1.0, the ",
-    "    points at each side and above and below receive a weight of 0.5, and corner ",
-    "    points receive a weight of 0.3.",
-    "    All 9 points are multiplied by their weights and summed, then divided by ",
-    "    the total weight to obtain the smoothed value. Any missing data points are ",
-    "    not included in the sum; points beyond the grid boundary are considered to ",
-    "    be missing. Thus the final result may be the result of an averaging with less ",
-    "    than 9 points.",
+    "    Smooth all grid points of a horizontal grid.",
+    "    Options is a comma separated list of \"key=value\" pairs with optional parameters.",
+    "",
+    "OPERATORS",
+    "    smooth   Smooth grid points",
+    "             Performs a N point smoothing on all input fields. The number of points used depend",
+    "             on the search radius (radius) and the maximum number of points (maxpoints).",
+    "             Per default all points within the search radius of 1degree are used.",
+    "             The weights for the points depend on the form of the curve and the distance.",
+    "             The implemented form of the curve is linear with constant default weights of 0.25",
+    "             at distance 0 (weight0) and at the search radius (weightR).",
+    "    smooth9  9 point smoothing",
+    "             Performs a 9 point smoothing on all fields with a quadrilateral curvilinear grid.",
+    "             The result at each grid point is a weighted average of the grid point plus",
+    "             the 8 surrounding points. The center point receives a weight of 1.0, the ",
+    "             points at each side and above and below receive a weight of 0.5, and corner ",
+    "             points receive a weight of 0.3.",
+    "             All 9 points are multiplied by their weights and summed, then divided by ",
+    "             the total weight to obtain the smoothed value. Any missing data points are ",
+    "             not included in the sum; points beyond the grid boundary are considered to ",
+    "             be missing. Thus the final result may be the result of an averaging with less ",
+    "             than 9 points.",
+    "",
+    "PARAMETER",
+    "    nsmooth    INTEGER  Number of times to smooth, default nsmooth=1",
+    "    radius     STRING   Search radius, default radius=1deg (units: deg, rad, km, m)",
+    "    maxpoints  INTEGER  Maximum number of points, default maxpoints=2147483647",
+    "    form       STRING   Form of the curve, default form=linear",
+    "    weight0    FLOAT    Weight at distance 0, default weight0=0.25",
+    "    weightR    FLOAT    Weight at the search radius, default weightR=0.25",
     NULL
 };
 
@@ -5043,19 +5130,20 @@ static const char *EcaCddHelp[] = {
     "    eca_cdd - Consecutive dry days index per time period",
     "",
     "SYNOPSIS",
-    "    eca_cdd[,R]  ifile ofile",
+    "    eca_cdd[,R[,N]]  ifile ofile",
     "",
     "DESCRIPTION",
     "    Let ifile be a time series of the daily precipitation amount RR, then the largest number ",
     "    of consecutive days where RR is less than R is counted. R is an optional parameter with ",
-    "    default R = 1 mm. A further output variable is the number of dry periods of more than 5 days.",
+    "    default R = 1 mm. A further output variable is the number of dry periods of more than N days.",
     "    The date information of a timestep in ofile is the date of the last contributing timestep in ifile.",
     "    The following variables are created: ",
     "    - consecutive_dry_days_index_per_time_period",
-    "    - number_of_cdd_periods_with_more_than_5days_per_time_period",
+    "    - number_of_cdd_periods_with_more_than_<N>days_per_time_period",
     "",
     "PARAMETER",
-    "    R  FLOAT   Precipitation threshold (unit: mm; default: R = 1 mm)",
+    "    R  FLOAT    Precipitation threshold (unit: mm; default: R = 1 mm)",
+    "    N  INTEGER  Minimum number of days exceeded (default: N = 5)",
     NULL
 };
 
@@ -5064,16 +5152,19 @@ static const char *EcaCfdHelp[] = {
     "    eca_cfd - Consecutive frost days index per time period",
     "",
     "SYNOPSIS",
-    "    eca_cfd  ifile ofile",
+    "    eca_cfd[,N]  ifile ofile",
     "",
     "DESCRIPTION",
     "    Let ifile be a time series of the daily minimum temperature TN, then the largest number of",
     "    consecutive days where TN < 0 °C is counted. Note that TN have to be given in units of Kelvin.",
-    "    A further output variable is the number of frost periods of more than 5 days.",
+    "    A further output variable is the number of frost periods of more than N days.",
     "    The date information of a timestep in ofile is the date of the last contributing timestep in ifile.",
     "    The following variables are created: ",
     "    - consecutive_frost_days_index_per_time_period",
-    "    - number_of_cfd_periods_with_more_than_5days_per_time_period",
+    "    - number_of_cfd_periods_with_more_than_<N>days_per_time_period",
+    "",
+    "PARAMETER",
+    "    N  INTEGER  Minimum number of days exceeded (default: N = 5)",
     NULL
 };
 
@@ -5082,20 +5173,21 @@ static const char *EcaCsuHelp[] = {
     "    eca_csu - Consecutive summer days index per time period",
     "",
     "SYNOPSIS",
-    "    eca_csu[,T]  ifile ofile",
+    "    eca_csu[,T[,N]]  ifile ofile",
     "",
     "DESCRIPTION",
     "    Let ifile be a time series of the daily maximum temperature TX, then the largest number of consecutive",
     "    days where TX > T is counted. The number T is an optional parameter with default T = 25°C.",
     "    Note that TN have to be given in units of Kelvin, whereas T have to be given in degrees Celsius.",
-    "    A further output variable is the number of summer periods of more than 5 days.",
+    "    A further output variable is the number of summer periods of more than N days.",
     "    The date information of a timestep in ofile is the date of the last contributing timestep in ifile.",
     "    The following variables are created: ",
     "    - consecutive_summer_days_index_per_time_period",
-    "    - number_of_csu_periods_with_more_than_5days_per_time_period",
+    "    - number_of_csu_periods_with_more_than_<N>days_per_time_period",
     "",
     "PARAMETER",
-    "    T  FLOAT   Temperature threshold (unit: °C; default: T = 25°C)",
+    "    T  FLOAT    Temperature threshold (unit: °C; default: T = 25°C)",
+    "    N  INTEGER  Minimum number of days exceeded (default: N = 5)",
     NULL
 };
 
@@ -5104,19 +5196,20 @@ static const char *EcaCwdHelp[] = {
     "    eca_cwd - Consecutive wet days index per time period",
     "",
     "SYNOPSIS",
-    "    eca_cwd[,R]  ifile ofile",
+    "    eca_cwd[,R[,N]]  ifile ofile",
     "",
     "DESCRIPTION",
     "    Let ifile be a time series of the daily precipitation amount RR, then the largest number ",
     "    of consecutive days where RR is at least R is counted. R is an optional parameter with ",
-    "    default R = 1 mm. A further output variable is the number of wet periods of more than 5 days.",
+    "    default R = 1 mm. A further output variable is the number of wet periods of more than N days.",
     "    The date information of a timestep in ofile is the date of the last contributing timestep in ifile.",
     "    The following variables are created: ",
     "    - consecutive_wet_days_index_per_time_period",
-    "    - number_of_cwd_periods_with_more_than_5days_per_time_period",
+    "    - number_of_cwd_periods_with_more_than_<N>days_per_time_period",
     "",
     "PARAMETER",
-    "    R  FLOAT   Precipitation threshold (unit: mm; default: R = 1 mm)",
+    "    R  FLOAT    Precipitation threshold (unit: mm; default: R = 1 mm)",
+    "    N  INTEGER  Minimum number of days exceeded (default: N = 5)",
     NULL
 };
 
@@ -5604,7 +5697,7 @@ static const char *EcaSdiiHelp[] = {
     "    wet days (RR > R) is written to ofile. R is an optional parameter with default R = 1 mm.",
     "    The date information of a timestep in ofile is the date of the last contributing timestep in ifile.",
     "    The following variables are created: ",
-    "    - simple_daily_intensitiy_index_per_time_period",
+    "    - simple_daily_intensity_index_per_time_period",
     "",
     "PARAMETER",
     "    R  FLOAT   Precipitation threshold (unit: mm; default: R = 1 mm)",
diff --git a/src/percentiles.c b/src/percentiles.c
index 58d7ced..454ff8f 100644
--- a/src/percentiles.c
+++ b/src/percentiles.c
@@ -60,7 +60,7 @@ double percentile_numpy(double *array, int len, double pn)
           int irank = 0;
           if      ( interpolation_method == LOWER   ) irank = (int) floor(rank);
           else if ( interpolation_method == HIGHER  ) irank = (int) ceil(rank);
-          else if ( interpolation_method == NEAREST ) irank = (int) round(rank);
+          else if ( interpolation_method == NEAREST ) irank = (int) lround(rank);
           // numpy is using around(), with rounds to the nearest even value
 
           if ( irank <   1 ) irank = 1;
diff --git a/src/pmlist.c b/src/pmlist.c
new file mode 100644
index 0000000..892ac4d
--- /dev/null
+++ b/src/pmlist.c
@@ -0,0 +1,366 @@
+#include "cdo_int.h"
+#include "pmlist.h"
+
+static
+void pml_init(pml_t *pml, const char *name)
+{
+  pml->size = 0;
+  pml->name = strdup(name);
+}
+
+
+pml_t *pml_create(const char *name)
+{
+  pml_t *pml = (pml_t*) Malloc(sizeof(pml_t));
+
+  pml_init(pml, name);
+
+  return pml;
+}
+
+
+void pml_destroy(pml_t *pml)
+{
+  if ( pml == NULL ) return;
+
+  for ( int i = 0; i < pml->size; ++i )
+    {
+      if ( pml->entry[i]->txt ) free(pml->entry[i]->txt);
+      if ( pml->entry[i]->name ) free(pml->entry[i]->name);
+      if ( pml->entry[i] ) Free(pml->entry[i]);
+    }
+
+  if ( pml->name ) free(pml->name);
+
+  Free(pml);
+}
+
+
+void pml_print(pml_t *pml)
+{
+  if ( pml == NULL ) return;
+
+  fprintf(stdout, "Parameter list: %s\n", pml->name);
+  fprintf(stdout, " Num  Name             Type  Size   Occ  Entries\n");
+
+  for ( int i = 0; i < pml->size; ++i )
+    {
+      pml_entry_t *entry = pml->entry[i];
+      fprintf(stdout, "%4d  %-16s %4d  %4d  %4d ",
+	      i+1, pml->entry[i]->name, pml->entry[i]->type, (int)pml->entry[i]->size, pml->entry[i]->occ);
+      int nout = pml->entry[i]->occ;
+      if ( nout > 8 ) nout = 8;
+
+      for ( int j = 0; j < nout; j++ )
+        {
+          switch (entry->type)
+            {
+            case PML_WORD: fprintf(stdout, " %s", ((char **)entry->ptr)[j]); break;
+            case PML_INT:  fprintf(stdout, " %d", ((int *)entry->ptr)[j]); break;
+            case PML_FLT:  fprintf(stdout, " %g", ((double *)entry->ptr)[j]); break;
+            }
+        }
+      fprintf(stdout, "\n");
+    }
+}
+
+
+int pml_add(pml_t *pml, const char *txt, const char *name, int type, void *ptr, size_t size)
+{
+  if ( pml->size >= MAX_PML_ENTRY )
+    {
+      fprintf(stderr, "Too many entries in parameter list %s! (Max = %d)\n", pml->name, MAX_PML_ENTRY);
+      return -1;
+    }
+
+  pml_entry_t *pml_entry = (pml_entry_t*) Malloc(sizeof(pml_entry_t));
+
+  pml_entry->txt  = strdup(txt);
+  pml_entry->name = strdup(name);
+  pml_entry->len  = strlen(name);
+  pml_entry->type = type;
+  pml_entry->ptr  = ptr;
+  pml_entry->size = size;
+  pml_entry->occ  = 0;
+
+  int entry = pml->size;
+  pml->entry[pml->size++] = pml_entry;
+
+  return entry;
+}
+
+
+int pml_num_par(pml_t *pml, int pid)
+{
+  int nocc = 0;
+
+  if ( pml && pid >= 0 && pid < pml->size ) nocc = pml->entry[pid]->occ;
+
+  return nocc;
+}
+
+
+int pml_num(pml_t *pml, const char *name)
+{
+  pml_entry_t *entry;
+  int i, nocc = 0;
+
+  if ( pml == NULL ) return nocc;
+
+  for ( i = 0; i < pml->size; i++ )
+    {
+      entry = pml->entry[i];
+      if ( strcmp(name, entry->name) == 0 )
+	{
+	  nocc = entry->occ;
+	  break;
+	}
+    }
+
+  if ( i == pml->size )
+    fprintf(stderr, "Parameter list entry %s not found in %s\n", name, pml->name);
+
+  return nocc;
+}
+
+void split_intstring(const char *intstr, int *first, int *last, int *inc);
+
+int pml_add_entry(pml_entry_t *entry, char *arg)
+{
+  int status = 0;
+
+  if ( entry->type == PML_INT )
+    {
+      int ival, first, last, inc;
+
+      split_intstring(arg, &first, &last, &inc);
+
+      if ( inc >= 0 )
+	{
+	  for ( ival = first; ival <= last; ival += inc )
+	    if ( entry->occ < (int) entry->size )
+	      ((int *) entry->ptr)[entry->occ++] = ival;
+	}
+      else
+	{
+	  for ( ival = first; ival >= last; ival += inc )
+	    if ( entry->occ < (int) entry->size )
+	      ((int *) entry->ptr)[entry->occ++] = ival;
+	}
+    }
+  else if ( entry->type == PML_FLT )
+    {
+      if ( entry->occ < (int) entry->size )
+	((double *) entry->ptr)[entry->occ++] = atof(arg);
+    }
+  else if ( entry->type == PML_WORD )
+    {
+      if ( entry->occ < (int) entry->size )
+	((char **) entry->ptr)[entry->occ++] = strdupx(arg);
+    }
+  else
+    {
+      fprintf(stderr, "Unsupported type!\n");
+    }
+
+  return status;
+}
+
+static
+void pml_process(pml_entry_t *entry, int argc, char **argv)
+{
+  for ( int i = 0; i < argc; ++i )
+    {
+      char *parg = argv[i];
+      if ( i == 0 )
+	{
+	  char *epos = strchr(parg, '=');
+	  if ( epos == NULL ) fprintf(stderr, "Internal problem, keyword not found!\n");
+	  parg += epos-parg+1;
+	}
+
+      pml_add_entry(entry, parg);
+    }
+}
+
+
+int pml_read(pml_t *pml, int argc, char **argv)
+{
+  pml_entry_t *entry = NULL;
+  pml_entry_t *pentry[MAX_PML_ENTRY];
+  int params[MAX_PML_ENTRY];
+  int num_par[MAX_PML_ENTRY];
+  int nparams = 0;
+  int i;
+  char *epos;
+  size_t len;
+  int bufsize = 0;
+  int status = 0;
+
+  if ( argc == 0 ) return 0;
+
+  for ( i = 0; i < argc; ++i )
+    {
+      len = strlen(argv[i]);
+      bufsize += len+1;
+    }
+
+  char *parbuf = (char*) Malloc(bufsize*sizeof(char));
+  memset(parbuf, 0, bufsize*sizeof(char));
+
+  int istart = 0;
+  while ( istart < argc )
+    {
+      epos = strchr(argv[istart], '=');
+      if ( epos == NULL )
+	{
+	  fprintf(stderr, "Parameter >%s< has no keyword!\n", argv[istart]);
+	  status = 1;
+	  goto END_LABEL;
+	}
+
+      len = epos - argv[istart];
+      for ( i = 0; i < pml->size; ++i )
+	{
+	  entry = pml->entry[i];
+	  if ( entry->len == len )
+	    if ( memcmp(entry->name, argv[istart], len) == 0 ) break;
+	}
+
+      if ( i == pml->size )
+	{
+	  fprintf(stderr, "Parameter >%s< has an invalid keyword!\n", argv[istart]);
+	  status = 2;
+	  goto END_LABEL;
+	}
+
+      num_par[nparams] = 0;
+      pentry[nparams]  = entry;
+      params[nparams]  = istart;
+      num_par[nparams] = 1;
+      
+      istart++;
+      for ( i = istart; i < argc; ++i )
+	{
+	  if ( *argv[i] == 0 ) { i++; break;}
+	  epos = strchr(argv[i], '=');
+	  if ( epos != NULL ) break;
+
+	  num_par[nparams]++;
+	}
+
+      istart = i;
+
+      nparams++;
+    }
+
+  for ( i = 0; i < nparams; ++i )
+    {
+      pml_process(pentry[i], num_par[i], &argv[params[i]]);
+    }
+
+
+ END_LABEL:
+
+  Free(parbuf);
+
+  return status;
+}
+
+
+bool pml_check_int(pml_t *pml, int pid, int *parlist, bool *flaglist, int par)
+{
+  bool found = false;
+  int npar = pml_num_par(pml, pid);
+  for ( int i = 0; i < npar; i++ )
+    if ( par == parlist[i] ) { found = true; flaglist[i] = true;/* break;*/}
+
+  return found;
+}
+
+
+bool pml_check_flt(pml_t *pml, int pid, double *parlist, bool *flaglist, double par)
+{
+  bool found = false;
+  int npar = pml_num_par(pml, pid);
+  for ( int i = 0; i < npar; i++ )
+    if ( fabs(par - parlist[i]) < 1.e-4 ) { found = true; flaglist[i] = true;/* break;*/}
+
+  return found;
+}
+
+
+bool pml_check_word(pml_t *pml, int pid, char **parlist, bool *flaglist, const char *par)
+{
+  bool found = false;
+  int npar = pml_num_par(pml, pid);
+  for ( int i = 0; i < npar; i++ )
+    if ( wildcardmatch(parlist[i], par) == 0 ) { found = true; flaglist[i] = true;/* break;*/}
+
+  return found;
+}
+
+
+bool pml_check_date(pml_t *pml, int pid, char **parlist, bool *flaglist, const char *par)
+{
+  bool found = false;
+  int npar = pml_num_par(pml, pid);
+  char wcdate[512];
+
+  if ( *par == ' ' ) ++par;
+
+  for ( int i = 0; i < npar; i++ )
+    {
+      strcpy(wcdate, parlist[i]);
+      strcat(wcdate, "*");
+      if ( wildcardmatch(wcdate, par) == 0 ) { found = true; flaglist[i] = true;/* break;*/}
+    }
+
+  return found;
+}
+
+void season_to_months(const char *season, int *imonths);
+
+bool pml_check_season(pml_t *pml, int pid, char **parlist, bool *flaglist, int month)
+{
+  assert(month>=1&&month<=12);
+  bool found = false;
+  int npar = pml_num_par(pml, pid);
+  int imon[13]; /* 1-12 ! */
+
+  for ( int i = 0; i < npar; i++ )
+    {
+      for ( int m = 0; m < 13; ++m ) imon[m] = 0;
+      season_to_months(parlist[i], imon);
+      if ( imon[month] ) { found = true; flaglist[i] = true;/* break;*/}
+    }
+
+  return found;
+}
+
+
+void pml_check_int_flag(pml_t *pml, int pid, int *parlist, bool *flaglist)
+{
+  int npar = pml_num_par(pml, pid);
+  for ( int i = 0; i < npar; ++i )
+    if ( flaglist[i] == false )
+      cdoWarning("%s >%d< not found!", pml->entry[pid]->txt, parlist[i]);
+}
+
+
+void pml_check_flt_flag(pml_t *pml, int pid, double *parlist, bool *flaglist)
+{
+  int npar = pml_num_par(pml, pid);
+  for ( int i = 0; i < npar; ++i )
+    if ( flaglist[i] == false )
+      cdoWarning("%s >%g< not found!", pml->entry[pid]->txt, parlist[i]);
+}
+
+
+void pml_check_word_flag(pml_t *pml, int pid, char **parlist, bool *flaglist)
+{
+  int npar = pml_num_par(pml, pid);
+  for ( int i = 0; i < npar; ++i )
+    if ( flaglist[i] == false )
+      cdoWarning("%s >%s< not found!", pml->entry[pid]->txt, parlist[i]);
+}
diff --git a/src/pmlist.h b/src/pmlist.h
new file mode 100644
index 0000000..ac20b90
--- /dev/null
+++ b/src/pmlist.h
@@ -0,0 +1,88 @@
+/*
+  This file is part of CDO. CDO is a collection of Operators to
+  manipulate and analyse Climate model Data.
+
+  Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.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.
+*/
+
+#ifndef _PMLIST_H
+#define _PMLIST_H
+
+#define  PML_INT         1
+#define  PML_FLT         2
+#define  PML_WORD        3
+#define  PML_DATE        4
+#define  PML_TIME        4
+
+#define  PML_INIT(name, size)                 memset(flag_##name, 0, size * sizeof(bool))
+#define  PML_DEF(name, size)                  bool flag_##name[size]
+#define  PML_DEF_INT(name, size)              int par_##name[size]; int name = 0; PML_DEF(name, size); PML_INIT(name, size)
+#define  PML_DEF_FLT(name, size)              double par_##name[size]; double name = 0; PML_DEF(name, size); PML_INIT(name, size)
+#define  PML_DEF_WORD(name, size)             char *par_##name[size]; const char *name = 0; PML_DEF(name, size); PML_INIT(name, size)
+#define  PML_ADD_INT(pml, name, size, txt)    PML_DEF_INT(name, size);  int pid_##name = pml_add(pml, txt, #name, PML_INT,  par_##name, sizeof(par_##name)/sizeof(int))
+#define  PML_ADD_FLT(pml, name, size, txt)    PML_DEF_FLT(name, size);  int pid_##name = pml_add(pml, txt, #name, PML_FLT,  par_##name, sizeof(par_##name)/sizeof(double))
+#define  PML_ADD_WORD(pml, name, size, txt)   PML_DEF_WORD(name, size); int pid_##name = pml_add(pml, txt, #name, PML_WORD, par_##name, sizeof(par_##name)/sizeof(char *))
+#define  PML_NOCC(pml, name)                  pml_num_par(pml, pid_##name)
+//#define  PML_NUM(pml, name)                   npar_##name = pml_num(pml, #name)
+
+#define  PML_CHECK_INT_FLAG(pml, name)        pml_check_int_flag(pml, pid_##name, par_##name, flag_##name)
+#define  PML_CHECK_FLT_FLAG(pml, name)        pml_check_flt_flag(pml, pid_##name, par_##name, flag_##name)
+#define  PML_CHECK_WORD_FLAG(pml, name)       pml_check_word_flag(pml, pid_##name, par_##name, flag_##name)
+#define  PML_CHECK_INT(pml, name)             pml_check_int(pml, pid_##name, par_##name, flag_##name, name)
+#define  PML_CHECK_FLT(pml, name)             pml_check_flt(pml, pid_##name, par_##name, flag_##name, name)
+#define  PML_CHECK_WORD(pml, name)            pml_check_word(pml, pid_##name, par_##name, flag_##name, name)
+#define  PML_CHECK_DATE(pml, name)            pml_check_date(pml, pid_##name, par_##name, flag_##name, name)
+#define  PML_CHECK_SEASON(pml, name, month)   pml_check_season(pml, pid_##name, par_##name, flag_##name, month)
+
+#define  MAX_PML_ENTRY    256
+
+typedef struct
+{
+  char *txt;
+  char *name;
+  size_t len;
+  void *ptr;
+  int type;
+  int occ;
+  size_t size;
+} pml_entry_t;
+
+
+typedef struct
+{
+  int size;
+  char *name;
+  pml_entry_t *entry[MAX_PML_ENTRY];
+} pml_t;
+
+
+pml_t *pml_create(const char *name);
+void pml_destroy(pml_t *pml);
+
+void pml_print(pml_t *pml);
+int pml_add(pml_t *pml, const char *txt, const char *name, int type, void *ptr, size_t size);
+int pml_num_par(pml_t *pml, int pid);
+int pml_add_entry(pml_entry_t *entry, char *arg);
+int pml_read(pml_t *pml, int argc, char **argv);
+
+bool pml_check_int(pml_t *pml, int pid, int *parlist, bool *flaglist, int par);
+bool pml_check_flt(pml_t *pml, int pid, double *parlist, bool *flaglist, double par);
+bool pml_check_word(pml_t *pml, int pid, char **parlist, bool *flaglist, const char *par);
+bool pml_check_date(pml_t *pml, int pid, char **parlist, bool *flaglist, const char *par);
+bool pml_check_season(pml_t *pml, int pid, char **parlist, bool *flaglist, int month);
+
+void pml_check_int_flag(pml_t *pml, int pid, int *parlist, bool *flaglist);
+void pml_check_flt_flag(pml_t *pml, int pid, double *parlist, bool *flaglist);
+void pml_check_word_flag(pml_t *pml, int pid, char **parlist, bool *flaglist);
+
+#endif  /* _PMLIST_H */
diff --git a/src/printinfo.h b/src/printinfo.h
index 4b5055f..a095bb5 100644
--- a/src/printinfo.h
+++ b/src/printinfo.h
@@ -1,5 +1,11 @@
 // This file is used in CDI and CDO !!!
 
+#if defined (HAVE_CONFIG_H)
+#  include "../src/config.h"
+#endif
+
+#include <stdio.h>
+
 #define DATE_FORMAT "%5.4d-%2.2d-%2.2d"
 #define TIME_FORMAT "%2.2d:%2.2d:%2.2d"
 
@@ -134,21 +140,24 @@ void printFiletype(int streamID, int vlistID)
 static
 void printGridInfo(int vlistID)
 {
-  int ngrids, index;
-  int gridID, gridtype, trunc, gridsize, xsize, ysize, xysize;
   char xname[CDI_MAX_NAME], yname[CDI_MAX_NAME], xunits[CDI_MAX_NAME], yunits[CDI_MAX_NAME];
   unsigned char uuidOfHGrid[CDI_UUID_SIZE];
 
-  ngrids = vlistNgrids(vlistID);
-  for ( index = 0; index < ngrids; index++ )
+  int ngrids = vlistNgrids(vlistID);
+  for ( int index = 0; index < ngrids; index++ )
     {
-      gridID   = vlistGrid(vlistID, index);
-      gridtype = gridInqType(gridID);
-      trunc    = gridInqTrunc(gridID);
-      gridsize = gridInqSize(gridID);
-      xsize    = gridInqXsize(gridID);
-      ysize    = gridInqYsize(gridID);
-      xysize   = xsize*ysize;
+      int gridID   = vlistGrid(vlistID, index);
+      int gridtype = gridInqType(gridID);
+      int trunc    = gridInqTrunc(gridID);
+      int gridsize = gridInqSize(gridID);
+      int xsize    = gridInqXsize(gridID);
+      int ysize    = gridInqYsize(gridID);
+      int xysize   = xsize*ysize;
+      // int prec     = gridInqPrec(gridID);
+
+      // int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
+      int dig = 7;
+
       gridInqXname(gridID, xname);
       gridInqYname(gridID, yname);
       gridInqXunits(gridID, xunits);
@@ -164,14 +173,9 @@ void printGridInfo(int vlistID)
 	   gridtype == GRID_GAUSSIAN ||
 	   gridtype == GRID_GAUSSIAN_REDUCED )
 	{
-          int lxcoord = 1, lycoord = 1;
-	  double xfirst = 0.0, xlast = 0.0;
-	  double yfirst = 0.0, ylast = 0.0;
-	  double xinc = 0.0, yinc = 0.0;
-
-	  yfirst = gridInqYval(gridID, 0);
-	  ylast  = gridInqYval(gridID, ysize-1);
-	  yinc   = gridInqYinc(gridID);
+	  double yfirst = gridInqYval(gridID, 0);
+	  double ylast  = gridInqYval(gridID, ysize-1);
+	  double yinc   = gridInqYinc(gridID);
 
           fprintf(stdout, " : points=%d", gridsize);
 	  if ( gridtype == GRID_GAUSSIAN_REDUCED )
@@ -184,20 +188,21 @@ void printGridInfo(int vlistID)
 
 	  fprintf(stdout, "\n");
 
-          if ( gridInqXvals(gridID, NULL) == 0 ) lxcoord = 0;
-          if ( gridInqYvals(gridID, NULL) == 0 ) lycoord = 0;
+          bool lxcoord = true, lycoord = true;
+          if ( gridInqXvals(gridID, NULL) == 0 ) lxcoord = false;
+          if ( gridInqYvals(gridID, NULL) == 0 ) lycoord = false;
 
 	  if ( xsize > 0 && lxcoord )
 	    {
-              xfirst = gridInqXval(gridID, 0);
-              xlast  = gridInqXval(gridID, xsize-1);
-              xinc   = gridInqXinc(gridID);
-              fprintf(stdout, "%33s : %g", xname, xfirst);
+              double xfirst = gridInqXval(gridID, 0);
+              double xlast  = gridInqXval(gridID, xsize-1);
+              double xinc   = gridInqXinc(gridID);
+              fprintf(stdout, "%33s : %.*g", xname, dig, xfirst);
               if ( xsize > 1 )
                 {
-                  fprintf(stdout, " to %g", xlast);
+                  fprintf(stdout, " to %.*g", dig, xlast);
                   if ( IS_NOT_EQUAL(xinc, 0) )
-                    fprintf(stdout, " by %g", xinc);
+                    fprintf(stdout, " by %.*g", dig, xinc);
                 }
               fprintf(stdout, " %s", xunits);
               if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
@@ -206,12 +211,12 @@ void printGridInfo(int vlistID)
 
 	  if ( ysize > 0 && lycoord )
 	    {
-	      fprintf(stdout, "%33s : %g", yname, yfirst);
+	      fprintf(stdout, "%33s : %.*g", yname, dig, yfirst);
 	      if ( ysize > 1 )
                 {
-                  fprintf(stdout, " to %g", ylast);
+                  fprintf(stdout, " to %.*g", dig, ylast);
                   if ( IS_NOT_EQUAL(yinc, 0) && gridtype != GRID_GAUSSIAN && gridtype != GRID_GAUSSIAN_REDUCED )
-                    fprintf(stdout, " by %g", yinc);
+                    fprintf(stdout, " by %.*g", dig, yinc);
                 }
               fprintf(stdout, " %s", yunits);
 	      fprintf(stdout, "\n");
@@ -219,12 +224,11 @@ void printGridInfo(int vlistID)
 
 	  if ( gridIsRotated(gridID) )
 	    {
-	      double lonpole, latpole, angle;
-	      lonpole = gridInqXpole(gridID);
-	      latpole = gridInqYpole(gridID);
-	      angle   = gridInqAngle(gridID);
-	      fprintf(stdout, "%33s : lon=%g  lat=%g", "northpole", lonpole, latpole);
-	      if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, "  angle=%g", angle);
+	      double lonpole = gridInqXpole(gridID);
+	      double latpole = gridInqYpole(gridID);
+	      double angle   = gridInqAngle(gridID);
+	      fprintf(stdout, "%33s : lon=%.*g  lat=%.*g", "northpole", dig, lonpole, dig, latpole);
+	      if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, "  angle=%.*g", dig, angle);
 	      fprintf(stdout, "\n");
 	    }
 
@@ -264,9 +268,8 @@ void printGridInfo(int vlistID)
 	}
       else if ( gridtype == GRID_GME )
 	{
-	  int ni, nd;
-	  ni = gridInqGMEni(gridID);
-	  nd = gridInqGMEnd(gridID);
+	  int ni = gridInqGMEni(gridID);
+	  int nd = gridInqGMEnd(gridID);
 	  fprintf(stdout, " : points=%d  nd=%d  ni=%d\n", gridsize, nd, ni);
 	}
       else if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
@@ -301,20 +304,17 @@ void printGridInfo(int vlistID)
 
 	  if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
 	    {
-	      int i;
-	      double *xvals, *yvals;
-	      double xfirst, xlast, yfirst, ylast;
-	      xvals = (double*) malloc((size_t)gridsize*sizeof(double));
-	      yvals = (double*) malloc((size_t)gridsize*sizeof(double));
+	      double *xvals = (double*) malloc((size_t)gridsize*sizeof(double));
+	      double *yvals = (double*) malloc((size_t)gridsize*sizeof(double));
 
 	      gridInqXvals(gridID, xvals);
 	      gridInqYvals(gridID, yvals);
 
-	      xfirst = xvals[0];
-	      xlast  = xvals[0];
-	      yfirst = yvals[0];
-	      ylast  = yvals[0];
-	      for ( i = 1; i < gridsize; i++ )
+	      double xfirst = xvals[0];
+	      double xlast  = xvals[0];
+	      double yfirst = yvals[0];
+	      double ylast  = yvals[0];
+	      for ( int i = 1; i < gridsize; i++ )
 		{
 		  if ( xvals[i] < xfirst ) xfirst = xvals[i];
 		  if ( xvals[i] > xlast  ) xlast  = xvals[i];
@@ -322,10 +322,10 @@ void printGridInfo(int vlistID)
 		  if ( yvals[i] > ylast  ) ylast  = yvals[i];
 		}
 
-	      fprintf(stdout, "%33s : %g to %g %s", xname, xfirst, xlast, xunits);
+	      fprintf(stdout, "%33s : %.*g to %.*g %s", xname, dig, xfirst, dig, xlast, xunits);
 	      if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
 	      fprintf(stdout, "\n");
-	      fprintf(stdout, "%33s : %g to %g %s\n", yname, yfirst, ylast, yunits);
+	      fprintf(stdout, "%33s : %.*g to %.*g %s\n", yname, dig, yfirst, dig, ylast, yunits);
 
 	      free(xvals);
 	      free(yvals);
@@ -385,19 +385,20 @@ void printGridInfo(int vlistID)
 static
 void printZaxisInfo(int vlistID)
 {
-  int zaxisID, zaxistype, levelsize, levelID;
-  int ltype;
-  double *levels = NULL;
   char zaxisname[CDI_MAX_NAME], zname[CDI_MAX_NAME], zunits[CDI_MAX_NAME];
 
   int nzaxis = vlistNzaxis(vlistID);
-  for ( int index = 0; index < nzaxis; index++)
+  for ( int index = 0; index < nzaxis; index++ )
     {
-      double zfirst = 0, zlast = 0, zinc = 0;
-      zaxisID   = vlistZaxis(vlistID, index);
-      zaxistype = zaxisInqType(zaxisID);
-      ltype     = zaxisInqLtype(zaxisID);
-      levelsize = zaxisInqSize(zaxisID);
+      double zinc = 0;
+      int zaxisID   = vlistZaxis(vlistID, index);
+      int zaxistype = zaxisInqType(zaxisID);
+      int ltype     = zaxisInqLtype(zaxisID);
+      int levelsize = zaxisInqSize(zaxisID);
+      int prec      = zaxisInqPrec(zaxisID);
+
+      int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
+
       zaxisName(zaxistype, zaxisname);
       zaxisInqName(zaxisID, zname);
       zaxisInqUnits(zaxisID, zunits);
@@ -411,15 +412,16 @@ void printZaxisInfo(int vlistID)
       fprintf(stdout, " levels=%d", levelsize);
       fprintf(stdout, "\n");
 
-      levels = (double*) malloc((size_t)levelsize*sizeof(double));
+      double *levels = (double*) malloc((size_t)levelsize*sizeof(double));
       zaxisInqLevels(zaxisID, levels);
 
       if ( !(zaxistype == ZAXIS_SURFACE && levelsize == 1 && !(fabs(levels[0]) > 0)) )
         {
-          zfirst = levels[0];
-          zlast  = levels[levelsize-1];
+          double zfirst = levels[0];
+          double zlast  = levels[levelsize-1];
           if ( levelsize > 2 )
             {
+              int levelID;
               zinc = (levels[levelsize-1] - levels[0]) / (levelsize-1);
               for ( levelID = 2; levelID < levelsize; ++levelID )
                 if ( fabs(fabs(levels[levelID] - levels[levelID-1]) - zinc) > 0.001*zinc ) break;
@@ -427,12 +429,12 @@ void printZaxisInfo(int vlistID)
               if ( levelID < levelsize ) zinc = 0;
             }
 
-          fprintf(stdout, "%33s : %g", zname, zfirst);
+          fprintf(stdout, "%33s : %.*g", zname, dig, zfirst);
           if ( levelsize > 1 )
             {
-              fprintf(stdout, " to %g", zlast);
+              fprintf(stdout, " to %.*g", dig, zlast);
               if ( IS_NOT_EQUAL(zinc, 0) )
-                fprintf(stdout, " by %g", zinc);
+                fprintf(stdout, " by %.*g", dig, zinc);
             }
           fprintf(stdout, " %s", zunits);
           fprintf(stdout, "\n");
@@ -447,14 +449,14 @@ void printZaxisInfo(int vlistID)
 
           level1 = zaxisInqLbound(zaxisID, 0);
           level2 = zaxisInqUbound(zaxisID, 0);
-          fprintf(stdout, "%.9g-%.9g", level1, level2);
+          fprintf(stdout, "%.*g-%.*g", dig, level1, dig, level2);
           if ( levelsize > 1 )
             {
               level1 = zaxisInqLbound(zaxisID, levelsize-1);
               level2 = zaxisInqUbound(zaxisID, levelsize-1);
-              fprintf(stdout, " to %.9g-%.9g", level1, level2);
+              fprintf(stdout, " to %.*g-%.*g", dig, level1, dig, level2);
               if ( IS_NOT_EQUAL(zinc, 0) )
-                fprintf(stdout, " by %g", zinc);
+                fprintf(stdout, " by %.*g", dig, zinc);
             }
           fprintf(stdout, " %s", zunits);
           fprintf(stdout, "\n");
@@ -566,7 +568,6 @@ static
 void printTimesteps(int streamID, int taxisID, int verbose)
 {
   int nrecs;
-  int vdate, vtime;
   struct datetime {
     int vdate;
     int vtime;
@@ -585,10 +586,19 @@ void printTimesteps(int streamID, int taxisID, int verbose)
   int nfact = 1;
   int tsID = 0;
 
+#ifdef CDO
+  dtlist_type *dtlist = dtlist_new();
+#endif
   while ( (nrecs = streamInqTimestep(streamID, tsID)) )
     {
-      vdate = taxisInqVdate(taxisID);
-      vtime = taxisInqVtime(taxisID);
+#ifdef CDO
+      dtlist_taxisInqTimestep(dtlist, taxisID, 0);
+      int vdate = dtlist_get_vdate(dtlist, 0);
+      int vtime = dtlist_get_vtime(dtlist, 0);
+#else
+      int vdate = taxisInqVdate(taxisID);
+      int vtime = taxisInqVtime(taxisID);
+#endif
 
       if ( verbose || tsID < NUM_TIMESTEP )
 	{
@@ -616,6 +626,9 @@ void printTimesteps(int streamID, int taxisID, int verbose)
       tsID++;
     }
 
+#ifdef CDO
+  dtlist_delete(dtlist);
+#endif
   if ( nvdatetime )
     {
       fprintf(stdout, "\n");
@@ -630,8 +643,8 @@ void printTimesteps(int streamID, int taxisID, int verbose)
         }
       for ( int i = toff; i < nvdatetime; ++i )
 	{
-	  vdate = next_vdatetime->vdate;
-	  vtime = next_vdatetime->vtime;
+	  int vdate = next_vdatetime->vdate;
+	  int vtime = next_vdatetime->vtime;
 	  ntimeout = printDateTime(ntimeout, vdate, vtime);
 	  next_vdatetime = next_vdatetime->next;
 	}
diff --git a/src/process.c b/src/process.c
index 19410e0..422f921 100644
--- a/src/process.c
+++ b/src/process.c
@@ -700,7 +700,7 @@ int checkStreamCnt(void)
     {
       if ( Process[processID].streamNames[i].args[0] == '-' )
         {
-          cdoAbort("Output file name %s must not begin with \"-\"!\n",
+          cdoAbort("Output file name %s must not begin with \"-\"!",
                    Process[processID].streamNames[i].args);
         }
       else if ( !obase )
diff --git a/src/pstream.c b/src/pstream.c
index d66055a..30ce81c 100644
--- a/src/pstream.c
+++ b/src/pstream.c
@@ -285,268 +285,282 @@ int pstreamIsPipe(int pstreamID)
   return pstreamptr->ispipe;
 }
 
-
-int pstreamOpenRead(const argument_t *argument)
+static
+void pstreamOpenReadPipe(const argument_t *argument, pstream_t *pstreamptr)
 {
-  PSTREAM_INIT();
-
-  pstream_t *pstreamptr = pstream_new_entry();
-  if ( ! pstreamptr ) Error("No memory");
-
+#if defined(HAVE_LIBPTHREAD)
   int pstreamID = pstreamptr->self;
 
-  int ispipe = argument->args[0] == '-';
+  char *pipename = (char*) Malloc(16);
+  // struct sched_param param;
+  
+  argument_t *newargument = (argument_t*) Malloc(sizeof(argument_t));
+  newargument->argc = argument->argc + 1;
+  newargument->argv = (char **) Malloc(newargument->argc*sizeof(char *));
+  memcpy(newargument->argv, argument->argv, argument->argc*sizeof(char *));
+
+  char *operatorArg  = argument->argv[0];
+  char *operatorName = getOperatorName(operatorArg);
+
+  size_t len = strlen(argument->args);
+  char *newarg = (char*) Malloc(len+16);
+  strcpy(newarg, argument->args);
+  sprintf(pipename, "(pipe%d.%d)", processSelf() + 1, processInqChildNum() + 1);
+  newarg[len] = ' ';
+  strcpy(&newarg[len+1], pipename);
+
+  newargument->argv[argument->argc] = pipename;
+  newargument->args = newarg;
   /*
-  printf("pstreamOpenRead: args >%s<\n", argument->args);
-  for ( int i = 0; i < argument->argc; ++i )
-    printf("pstreamOpenRead: arg %d >%s<\n", i, argument->argv[i]);
+    printf("pstreamOpenRead: new args >%s<\n", newargument->args);
+    for ( int i = 0; i < newargument->argc; ++i )
+    printf("pstreamOpenRead: new arg %d >%s<\n", i, newargument->argv[i]);
   */
-  if ( ispipe )
-    {
-#if defined(HAVE_LIBPTHREAD)
-      char *operatorArg;
-      char *operatorName;
-      char *newarg;
-      char *pipename = (char*) Malloc(16);
-      int rval;
-      pthread_t thrID;
-      pthread_attr_t attr;
-      // struct sched_param param;
-      size_t len;
-      size_t stacksize;
-      int status;
-      argument_t *newargument = (argument_t*) Malloc(sizeof(argument_t));
-
-      newargument->argc = argument->argc + 1;
-      newargument->argv = (char **) Malloc(newargument->argc*sizeof(char *));
-      memcpy(newargument->argv, argument->argv, argument->argc*sizeof(char *));
-
-      operatorArg  = argument->argv[0];
-      operatorName = getOperatorName(operatorArg);
-
-      len = strlen(argument->args);
-      newarg = (char*) Malloc(len+16);
-      strcpy(newarg, argument->args);
-      sprintf(pipename, "(pipe%d.%d)", processSelf() + 1, processInqChildNum() + 1);
-      newarg[len] = ' ';
-      strcpy(&newarg[len+1], pipename);
-
-      newargument->argv[argument->argc] = pipename;
-      newargument->args = newarg;
-      /*
-      printf("pstreamOpenRead: new args >%s<\n", newargument->args);
-      for ( int i = 0; i < newargument->argc; ++i )
-	printf("pstreamOpenRead: new arg %d >%s<\n", i, newargument->argv[i]);
-      */
-      pstreamptr->ispipe    = TRUE;
-      pstreamptr->name      = pipename;
-      pstreamptr->rthreadID = pthread_self();
-      pstreamptr->pipe      = pipeNew();
-      pstreamptr->argument  = (void *) newargument;
+  pstreamptr->ispipe    = TRUE;
+  pstreamptr->name      = pipename;
+  pstreamptr->rthreadID = pthread_self();
+  pstreamptr->pipe      = pipeNew();
+  pstreamptr->argument  = (void *) newargument;
  
-      if ( ! cdoSilentMode )
-	cdoPrint("Started child process \"%s\".", newarg+1);
-
-      status = pthread_attr_init(&attr);
-      if ( status ) SysError("pthread_attr_init failed for '%s'", newarg+1);
-      status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-      if ( status ) SysError("pthread_attr_setdetachstate failed for '%s'", newarg+1);
-      /*
-      param.sched_priority = 0;
-      status = pthread_attr_setschedparam(&attr, &param);
-      if ( status ) SysError("pthread_attr_setschedparam failed for '%s'", newarg+1);
-      */
-      /* status = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); */
-      /* if ( status ) SysError("pthread_attr_setinheritsched failed for '%s'", newarg+1); */
+  if ( ! cdoSilentMode )
+    cdoPrint("Started child process \"%s\".", newarg+1);
+
+  pthread_attr_t attr;
+  int status = pthread_attr_init(&attr);
+  if ( status ) SysError("pthread_attr_init failed for '%s'", newarg+1);
+  status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+  if ( status ) SysError("pthread_attr_setdetachstate failed for '%s'", newarg+1);
+  /*
+    param.sched_priority = 0;
+    status = pthread_attr_setschedparam(&attr, &param);
+    if ( status ) SysError("pthread_attr_setschedparam failed for '%s'", newarg+1);
+  */
+  /* status = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); */
+  /* if ( status ) SysError("pthread_attr_setinheritsched failed for '%s'", newarg+1); */
 
-      pthread_attr_getscope(&attr, &pthreadScope);
+  pthread_attr_getscope(&attr, &pthreadScope);
 
-      /* status = pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); */
-      /* if ( status ) SysError("pthread_attr_setscope failed for '%s'", newarg+1); */
-      /* If system scheduling scope is specified, then the thread is scheduled against all threads in the system */
-      /* pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); */
+  /* status = pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); */
+  /* if ( status ) SysError("pthread_attr_setscope failed for '%s'", newarg+1); */
+  /* If system scheduling scope is specified, then the thread is scheduled against all threads in the system */
+  /* pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); */
 
-      status = pthread_attr_getstacksize(&attr, &stacksize);
-      if ( stacksize < 2097152 )
-	{
-	  stacksize = 2097152;
-	  pthread_attr_setstacksize(&attr, stacksize);
-	}
+  size_t stacksize = 0;
+  status = pthread_attr_getstacksize(&attr, &stacksize);
+  if ( stacksize < 2097152 )
+    {
+      stacksize = 2097152;
+      pthread_attr_setstacksize(&attr, stacksize);
+    }
 
-      rval = pthread_create(&thrID, &attr, operatorModule(operatorName), newargument);
-      if ( rval != 0 )
-	{
-	  errno = rval;
-	  SysError("pthread_create failed for '%s'", newarg+1);
-	}
+  pthread_t thrID;
+  int rval = pthread_create(&thrID, &attr, operatorModule(operatorName), newargument);
+  if ( rval != 0 )
+    {
+      errno = rval;
+      SysError("pthread_create failed for '%s'", newarg+1);
+    }
 
-      /* Free(operatorName); */
-      processAddStream(pstreamID);
-      /*      pipeInqInfo(pstreamID); */
-      if ( PSTREAM_Debug ) Message("pipe %s", pipename);
+  /* Free(operatorName); */
+  processAddStream(pstreamID);
+  /*      pipeInqInfo(pstreamID); */
+  if ( PSTREAM_Debug ) Message("pipe %s", pipename);
 #else
-      cdoAbort("Cannot use pipes, pthread support not compiled in!");
+  cdoAbort("Cannot use pipes, pthread support not compiled in!");
 #endif
-    }
-  else
-    {
-      size_t len, i;
-      int nfiles = 1, j;
-      char *filename = NULL;
-      const char *pch;
+}
 
-      len = strlen(argument->args);
+static
+void pstreamCreateFilelist(const argument_t *argument, pstream_t *pstreamptr)
+{
+  size_t i;
+  size_t len = strlen(argument->args);
 
-      for ( i = 0; i < len; i++ )
-	if ( argument->args[i] == ':' ) break;
+  for ( i = 0; i < len; i++ )
+    if ( argument->args[i] == ':' ) break;
 
-      if ( i < len )
-	{
-	  pch = &argument->args[i+1];
-	  len -= (i+1);
-	  if ( len && ( strncmp(argument->args, "filelist:", 9) == 0 || 
-			strncmp(argument->args, "flist:", 6) == 0 ) )
-	    {
-	      for ( i = 0; i < len; i++ ) if ( pch[i] == ',' ) nfiles++;
+  if ( i < len )
+    {
+      int nfiles = 1, j;
 
-	      if ( nfiles == 1 )
-		{
-		  char line[4096];
-		  FILE *fp, *fp2;
-		  fp = fopen(pch, "r");
-		  if ( fp == NULL ) cdoAbort("Open failed on %s", pch);
-
-		  if ( cdoVerbose )
-		    cdoPrint("Reading file names from %s", pch);
-
-		  /* find number of files */
-		  nfiles = 0;
-		  while ( readline(fp, line, 4096) )
-		    {
-		      if ( line[0] == '#' || line[0] == '\0' || line[0] == ' ' ) continue;
-
-		      fp2 = fopen(line, "r" );
-		      if ( fp2 == NULL ) cdoAbort("Open failed on %s", line);
-		      fclose(fp2);
-		      nfiles++;
-		      if ( cdoVerbose )
-			cdoPrint("File number %d is %s", nfiles, line);
-		    }
-
-		  if ( nfiles == 0 ) cdoAbort("No imput file found in %s", pch);
-
-		  pstreamptr->mfiles = nfiles;
-		  pstreamptr->mfnames = (char **) Malloc(nfiles*sizeof(char *));
+      const char *pch = &argument->args[i+1];
+      len -= (i+1);
+      if ( len && ( strncmp(argument->args, "filelist:", 9) == 0 || 
+                    strncmp(argument->args, "flist:", 6) == 0 ) )
+        {
+          for ( i = 0; i < len; i++ ) if ( pch[i] == ',' ) nfiles++;
+
+          if ( nfiles == 1 )
+            {
+              char line[4096];
+              FILE *fp, *fp2;
+              fp = fopen(pch, "r");
+              if ( fp == NULL ) cdoAbort("Open failed on %s", pch);
+              
+              if ( cdoVerbose )
+                cdoPrint("Reading file names from %s", pch);
+
+              /* find number of files */
+              nfiles = 0;
+              while ( readline(fp, line, 4096) )
+                {
+                  if ( line[0] == '#' || line[0] == '\0' || line[0] == ' ' ) continue;
+
+                  fp2 = fopen(line, "r" );
+                  if ( fp2 == NULL ) cdoAbort("Open failed on %s", line);
+                  fclose(fp2);
+                  nfiles++;
+                  if ( cdoVerbose )
+                    cdoPrint("File number %d is %s", nfiles, line);
+                }
+
+              if ( nfiles == 0 ) cdoAbort("No imput file found in %s", pch);
+
+              pstreamptr->mfiles = nfiles;
+              pstreamptr->mfnames = (char **) Malloc(nfiles*sizeof(char *));
+		  
+              rewind(fp);
+
+              nfiles = 0;
+              while ( readline(fp, line, 4096) )
+                {
+                  if ( line[0] == '#' || line[0] == '\0' ||
+                       line[0] == ' ' ) continue;
+
+                  pstreamptr->mfnames[nfiles] = strdupx(line);
+                  nfiles++;
+                }
+
+              fclose(fp);
+            }
+          else
+            {
+              char line[65536];
+
+              pstreamptr->mfiles = nfiles;
+              pstreamptr->mfnames = (char **) Malloc(nfiles*sizeof(char *));
 		  
-		  rewind(fp);
+              strcpy(line, pch);
+              for ( i = 0; i < len; i++ ) if ( line[i] == ',' ) line[i] = 0;
+              
+              i = 0;
+              for ( j = 0; j < nfiles; j++ )
+                {
+                  pstreamptr->mfnames[j] = strdupx(&line[i]);
+                  i += strlen(&line[i]) + 1;
+                }
+            }
+        }
+      else if ( len && strncmp(argument->args, "ls:", 3) == 0 )
+        {
+          char line[4096];
+          char command[4096];
+          char *fnames[16384];
+          FILE *pfp;
 
-		  nfiles = 0;
-		  while ( readline(fp, line, 4096) )
-		    {
-		      if ( line[0] == '#' || line[0] == '\0' ||
-			   line[0] == ' ' ) continue;
+          strcpy(command, "ls ");
+          strcat(command, pch);
 
-		      pstreamptr->mfnames[nfiles] = strdupx(line);
-		      nfiles++;
-		    }
+          pfp = popen(command, "r");
+          if ( pfp == 0 )
+            SysError("popen %s failed", command);
 
-		  fclose(fp);
-		}
-	      else
-		{
-		  char line[65536];
+          nfiles = 0;
+          while ( readline(pfp, line, 4096) )
+            {
+              if ( nfiles >= 16384 ) cdoAbort("Too many input files (limit: 16384)");
+              fnames[nfiles++] = strdupx(line);
+            }
 
-		  pstreamptr->mfiles = nfiles;
-		  pstreamptr->mfnames = (char **) Malloc(nfiles*sizeof(char *));
-		  
-		  strcpy(line, pch);
-		  for ( i = 0; i < len; i++ ) if ( line[i] == ',' ) line[i] = 0;
-
-		  i = 0;
-		  for ( j = 0; j < nfiles; j++ )
-		    {
-		      pstreamptr->mfnames[j] = strdupx(&line[i]);
-		      i += strlen(&line[i]) + 1;
-		    }
-		}
-	    }
-	  else if ( len && strncmp(argument->args, "ls:", 3) == 0 )
-	    {
-	      char line[4096];
-	      char command[4096];
-	      char *fnames[16384];
-	      FILE *pfp;
-
-	      strcpy(command, "ls ");
-	      strcat(command, pch);
+          pclose(pfp);
 
-	      pfp = popen(command, "r");
-	      if ( pfp == 0 )
-		SysError("popen %s failed", command);
-
-	      nfiles = 0;
-	      while ( readline(pfp, line, 4096) )
-		{
-		  if ( nfiles >= 16384 ) cdoAbort("Too many input files (limit: 16384)");
-		  fnames[nfiles++] = strdupx(line);
-		}
+          pstreamptr->mfiles = nfiles;
+          pstreamptr->mfnames = (char **) Malloc(nfiles*sizeof(char *));
 
-	      pclose(pfp);
+          for ( j = 0; j < nfiles; j++ )
+            pstreamptr->mfnames[j] = fnames[j];
+        }
+    }
+}
 
-	      pstreamptr->mfiles = nfiles;
-	      pstreamptr->mfnames = (char **) Malloc(nfiles*sizeof(char *));
+static
+void pstreamOpenReadFile(const argument_t *argument, pstream_t *pstreamptr)
+{  
+  pstreamCreateFilelist(argument, pstreamptr);
 
-	      for ( j = 0; j < nfiles; j++ )
-		pstreamptr->mfnames[j] = fnames[j];
-	    }
-	}
+  size_t len;
+  char *filename = NULL;
 
-      if ( pstreamptr->mfiles )
-	{
-	  len = strlen(pstreamptr->mfnames[0]);
-	  filename = (char*) Malloc(len+1);
-	  strcpy(filename, pstreamptr->mfnames[0]);
-	  pstreamptr->nfiles = 1;
-	}
-      else
-	{
-	  len = strlen(argument->args);
-	  filename = (char*) Malloc(len+1);
-	  strcpy(filename, argument->args);
-	}
+  if ( pstreamptr->mfiles )
+    {
+      len = strlen(pstreamptr->mfnames[0]);
+      filename = (char*) Malloc(len+1);
+      strcpy(filename, pstreamptr->mfnames[0]);
+      pstreamptr->nfiles = 1;
+    }
+  else
+    {
+      len = strlen(argument->args);
+      filename = (char*) Malloc(len+1);
+      strcpy(filename, argument->args);
+    }
 
-      if ( PSTREAM_Debug ) Message("file %s", filename);
+  if ( PSTREAM_Debug ) Message("file %s", filename);
 
 #if defined(HAVE_LIBPTHREAD)
-      if ( cdoLockIO )
-	pthread_mutex_lock(&streamMutex);
-      else
-	pthread_mutex_lock(&streamOpenReadMutex);
+  if ( cdoLockIO )
+    pthread_mutex_lock(&streamMutex);
+  else
+    pthread_mutex_lock(&streamOpenReadMutex);
 #endif
-      int fileID = streamOpenRead(filename);
-      if ( fileID < 0 )
-        {
-          pstreamptr->isopen = FALSE;
-          cdiOpenError(fileID, "Open failed on >%s<", filename);
-        }
+  int fileID = streamOpenRead(filename);
+  if ( fileID < 0 )
+    {
+      pstreamptr->isopen = FALSE;
+      cdiOpenError(fileID, "Open failed on >%s<", filename);
+    }
       
-      if ( cdoDefaultFileType == CDI_UNDEFID )
-	cdoDefaultFileType = streamInqFiletype(fileID);
-      /*
-      if ( cdoDefaultInstID == CDI_UNDEFID )
-	cdoDefaultInstID = streamInqInstID(fileID);
-      */
-      cdoInqHistory(fileID);
+  if ( cdoDefaultFileType == CDI_UNDEFID )
+    cdoDefaultFileType = streamInqFiletype(fileID);
+  /*
+    if ( cdoDefaultInstID == CDI_UNDEFID )
+    cdoDefaultInstID = streamInqInstID(fileID);
+  */
+  cdoInqHistory(fileID);
 #if defined(HAVE_LIBPTHREAD)
-      if ( cdoLockIO )
-	pthread_mutex_unlock(&streamMutex);
-      else
-	pthread_mutex_unlock(&streamOpenReadMutex);
+  if ( cdoLockIO )
+    pthread_mutex_unlock(&streamMutex);
+  else
+    pthread_mutex_unlock(&streamOpenReadMutex);
 #endif
 
-      pstreamptr->mode   = 'r';
-      pstreamptr->name   = filename;
-      pstreamptr->fileID = fileID;
+  pstreamptr->mode   = 'r';
+  pstreamptr->name   = filename;
+  pstreamptr->fileID = fileID;
+}
+
+int pstreamOpenRead(const argument_t *argument)
+{
+  PSTREAM_INIT();
+
+  pstream_t *pstreamptr = pstream_new_entry();
+  if ( ! pstreamptr ) Error("No memory");
+
+  int pstreamID = pstreamptr->self;
+
+  int ispipe = argument->args[0] == '-';
+  /*
+  printf("pstreamOpenRead: args >%s<\n", argument->args);
+  for ( int i = 0; i < argument->argc; ++i )
+    printf("pstreamOpenRead: arg %d >%s<\n", i, argument->argv[i]);
+  */
+  if ( ispipe )
+    {
+      pstreamOpenReadPipe(argument, pstreamptr);
+    }
+  else
+    {
+      pstreamOpenReadFile(argument, pstreamptr);
     }
 
   if ( pstreamID < 0 ) cdiOpenError(pstreamID, "Open failed on >%s<", argument->args);
@@ -612,115 +626,135 @@ void query_user_exit(const char *argument)
     } /* end switch */
 }
 
-
-int pstreamOpenWrite(const argument_t *argument, int filetype)
+static
+int pstreamOpenWritePipe(const argument_t *argument, int filetype)
 {
   int pstreamID = -1;
-  pstream_t *pstreamptr;
-
-  PSTREAM_INIT();
-
-  int ispipe = strncmp(argument->args, "(pipe", 5) == 0;
-
-  if ( ispipe )
-    {
+  
 #if defined(HAVE_LIBPTHREAD)
-      if ( PSTREAM_Debug ) Message("pipe %s", argument->args);
-      pstreamID = pstreamFindID(argument->args);
-      if ( pstreamID == -1 ) Error("%s is not open!", argument->args);
+  if ( PSTREAM_Debug ) Message("pipe %s", argument->args);
+  pstreamID = pstreamFindID(argument->args);
+  if ( pstreamID == -1 ) Error("%s is not open!", argument->args);
 
-      pstreamptr = pstream_to_pointer(pstreamID);
+  pstream_t *pstreamptr = pstream_to_pointer(pstreamID);
 
-      pstreamptr->wthreadID = pthread_self();
-      pstreamptr->filetype = filetype;
-      processAddStream(pstreamID);
+  pstreamptr->wthreadID = pthread_self();
+  pstreamptr->filetype = filetype;
+  processAddStream(pstreamID);
 #endif
-    }
-  else
-    {
-      char *filename = (char*) Malloc(strlen(argument->args)+1);
 
-      pstreamptr = pstream_new_entry();
-      if ( ! pstreamptr ) Error("No memory");
+  return pstreamID;
+}
 
-      pstreamID = pstreamptr->self;
+static
+int pstreamOpenWriteFile(const argument_t *argument, int filetype)
+{
+  char *filename = (char*) Malloc(strlen(argument->args)+1);
+
+  pstream_t *pstreamptr = pstream_new_entry();
+  if ( ! pstreamptr ) Error("No memory");
+
+  int pstreamID = pstreamptr->self;
   
-      if ( PSTREAM_Debug ) Message("file %s", argument->args);
+  if ( PSTREAM_Debug ) Message("file %s", argument->args);
 
-      if ( filetype == CDI_UNDEFID ) filetype = FILETYPE_GRB;
+  if ( filetype == CDI_UNDEFID ) filetype = FILETYPE_GRB;
 
-      if ( cdoInteractive )
-	{
-	  int rstatus;
-	  struct stat stbuf;
+  if ( cdoInteractive )
+    {
+      struct stat stbuf;
 
-	  rstatus = stat(argument->args, &stbuf);
-	  /* If permanent file already exists, query user whether to overwrite or exit */
-	  if ( rstatus != -1 ) query_user_exit(argument->args);
-	}
+      int rstatus = stat(argument->args, &stbuf);
+      /* If permanent file already exists, query user whether to overwrite or exit */
+      if ( rstatus != -1 ) query_user_exit(argument->args);
+    }
+
+  if ( processNums() == 1 && ompNumThreads == 1 ) timer_start(timer_write);
 
-      if ( processNums() == 1 && ompNumThreads == 1 ) timer_start(timer_write);
 #if defined(HAVE_LIBPTHREAD)
-      if ( cdoLockIO )
-	pthread_mutex_lock(&streamMutex);
-      else
-	pthread_mutex_lock(&streamOpenWriteMutex);
+  if ( cdoLockIO )
+    pthread_mutex_lock(&streamMutex);
+  else
+    pthread_mutex_lock(&streamOpenWriteMutex);
 #endif
-      int fileID = streamOpenWrite(argument->args, filetype);
+
+  int fileID = streamOpenWrite(argument->args, filetype);
+  
 #if defined(HAVE_LIBPTHREAD)
-      if ( cdoLockIO )
-	pthread_mutex_unlock(&streamMutex);
-      else
-	pthread_mutex_unlock(&streamOpenWriteMutex);
+  if ( cdoLockIO )
+    pthread_mutex_unlock(&streamMutex);
+  else
+    pthread_mutex_unlock(&streamOpenWriteMutex);
 #endif
-      if ( processNums() == 1 && ompNumThreads == 1 ) timer_stop(timer_write);
-      if ( fileID < 0 ) cdiOpenError(fileID, "Open failed on >%s<", argument->args);
+  
+  if ( processNums() == 1 && ompNumThreads == 1 ) timer_stop(timer_write);
+  if ( fileID < 0 ) cdiOpenError(fileID, "Open failed on >%s<", argument->args);
 
-      cdoDefHistory(fileID, commandLine());
+  cdoDefHistory(fileID, commandLine());
 
-      if ( cdoDefaultByteorder != CDI_UNDEFID )
-	streamDefByteorder(fileID, cdoDefaultByteorder);
+  if ( cdoDefaultByteorder != CDI_UNDEFID )
+    streamDefByteorder(fileID, cdoDefaultByteorder);
 
-      if ( cdoCompress )
-	{
-	  if      ( filetype == FILETYPE_GRB )
-	    {
-	      cdoCompType  = COMPRESS_SZIP;
-	      cdoCompLevel = 0;
-	    }
-	  else if ( filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C )
-	    {
-	      cdoCompType  = COMPRESS_ZIP;
-	      cdoCompLevel = 1;
-	    }
-	}
+  if ( cdoCompress )
+    {
+      if      ( filetype == FILETYPE_GRB )
+        {
+          cdoCompType  = COMPRESS_SZIP;
+          cdoCompLevel = 0;
+        }
+      else if ( filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C )
+        {
+          cdoCompType  = COMPRESS_ZIP;
+          cdoCompLevel = 1;
+        }
+    }
 
-      if ( cdoCompType != COMPRESS_NONE )
-	{
-	  streamDefCompType(fileID, cdoCompType);
-	  streamDefCompLevel(fileID, cdoCompLevel);
+  if ( cdoCompType != COMPRESS_NONE )
+    {
+      streamDefCompType(fileID, cdoCompType);
+      streamDefCompLevel(fileID, cdoCompLevel);
 
-	  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_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("JPEG compression not available for non GRIB2 data!");
+      if ( cdoCompType == COMPRESS_JPEG && filetype != FILETYPE_GRB2 )
+        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!");
-	}
-      /*
-      if ( cdoDefaultInstID != CDI_UNDEFID )
-	streamDefInstID(fileID, cdoDefaultInstID);
-      */
-      strcpy(filename, argument->args);
+      if ( cdoCompType == COMPRESS_ZIP && (filetype != FILETYPE_NC4 && filetype != FILETYPE_NC4C) )
+        cdoWarning("Deflate compression not available for non NetCDF4 data!");
+    }
+  /*
+    if ( cdoDefaultInstID != CDI_UNDEFID )
+    streamDefInstID(fileID, cdoDefaultInstID);
+  */
+  strcpy(filename, argument->args);
+
+  pstreamptr->mode     = 'w';
+  pstreamptr->name     = filename;
+  pstreamptr->fileID   = fileID;
+  pstreamptr->filetype = filetype;
+
+  return pstreamID;
+}
+
+
+int pstreamOpenWrite(const argument_t *argument, int filetype)
+{
+  int pstreamID = -1;
+
+  PSTREAM_INIT();
+
+  int ispipe = strncmp(argument->args, "(pipe", 5) == 0;
 
-      pstreamptr->mode     = 'w';
-      pstreamptr->name     = filename;
-      pstreamptr->fileID   = fileID;
-      pstreamptr->filetype = filetype;
-   }
+  if ( ispipe )
+    {
+      pstreamID = pstreamOpenWritePipe(argument, filetype);
+    }
+  else
+    {
+      pstreamID = pstreamOpenWriteFile(argument, filetype);
+    }
 
   return pstreamID;
 }
@@ -930,7 +964,7 @@ int pstreamInqVlist(int pstreamID)
       if ( processNums() == 1 && ompNumThreads == 1 ) timer_stop(timer_read);
 
       int nsubtypes = vlistNsubtypes(vlistID);
-      if ( nsubtypes > 0 )
+      if ( nsubtypes > 1 )
         cdoWarning("Subtypes are unsupported, the processing results are possibly wrong!");
 
       if ( cdoDefaultTimeType != CDI_UNDEFID )
@@ -962,6 +996,8 @@ void pstreamDefVarlist(pstream_t *pstreamptr, int vlistID)
     cdoAbort("Internal problem, varlist already allocated!");
 
   int nvars = vlistNvars(vlistID);
+  assert(nvars>0);
+  
   varlist_t *varlist = (varlist_t*) Malloc(nvars*sizeof(varlist_t));
 
   for ( int varID = 0; varID < nvars; ++varID )
@@ -1231,8 +1267,8 @@ void pstreamCheckDatarange(pstream_t *pstreamptr, int varID, double *array, int
       if ( datatype == DATATYPE_INT8  || datatype == DATATYPE_UINT8 ||
 	   datatype == DATATYPE_INT16 || datatype == DATATYPE_UINT16 )
 	{
-	  smin = (int) round(smin);
-	  smax = (int) round(smax);
+	  smin = (int)lround(smin);
+	  smax = (int)lround(smax);
 	}
 
       double vmin = 0, vmax = 0;
@@ -1516,7 +1552,7 @@ void pstreamCloseAll(void)
       pstream_t *pstreamptr = _pstreamList[i].ptr;
       if ( pstreamptr && pstreamptr->isopen )
 	{
-	  if ( !pstreamptr->ispipe )
+	  if ( !pstreamptr->ispipe && pstreamptr->fileID != CDI_UNDEFID )
 	    {
 	      if ( PSTREAM_Debug )
 		Message("Close file %s id %d", pstreamptr->name, pstreamptr->fileID);
diff --git a/src/pthread_debug.c b/src/pthread_debug.c
index 3755bf6..9c17dfa 100644
--- a/src/pthread_debug.c
+++ b/src/pthread_debug.c
@@ -5,7 +5,6 @@
 #include <stdio.h>
 
 
-
 #if defined(HAVE_LIBPTHREAD)
 #include <pthread.h>
 #include <errno.h>
@@ -79,6 +78,8 @@ void print_pthread_attr(const char *caller, pthread_attr_t *attr)
 
 void print_pthread_mutexattr(const char *caller,  pthread_mutexattr_t *m_attr)
 {
+  (void) caller;
+  (void) m_attr;
   /*
 #if defined(_POSIX_THREAD_PRIO_PROTECT) && defined(_POSIX_THREAD_PRIO_INHERIT)
   {
@@ -114,6 +115,9 @@ void print_pthread_condattr(const char *caller, pthread_condattr_t *c_attr)
   pthread_condattr_getpshared(c_attr, &pshared);
   POUT2(caller, pshared, PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE);
   }
+#else
+  (void) caller;
+  (void) c_attr;
 #endif
 }
 
@@ -147,13 +151,14 @@ int Pthread_create(const char *caller, pthread_t *th,
 
   //if ( PTHREAD_Debug ) Message("-%s (thID = %ld, status = %d)", caller, (long) *th, status);
 
-  return (status);
+  return status;
 }
 
 
 int Pthread_join(const char *caller, pthread_t th, void **thread_return)
 {
   int status;
+  (void) caller;
 
   //  if ( PTHREAD_Debug ) Message("+%s (thID = %ld)", caller, (void *) th);
 
@@ -161,7 +166,7 @@ int Pthread_join(const char *caller, pthread_t th, void **thread_return)
 
   // if ( PTHREAD_Debug ) Message("-%s (thID = %ld, status = %d)", caller, (void *) th, status);
 
-  return (status);
+  return status;
 }
 
 
diff --git a/src/readline.c b/src/readline.c
index b2d0e20..41cdd5d 100644
--- a/src/readline.c
+++ b/src/readline.c
@@ -23,7 +23,12 @@ int readline(FILE *fp, char *line, int len)
 
   while ( (ichar = fgetc(fp)) != EOF )
     {
-      if ( ichar == '\r' ) break;
+      if ( ichar == '\r' )
+        {
+          if ( (ichar = fgetc(fp)) != EOF )
+            if ( ichar != '\n' ) ungetc(ichar, fp);
+          break;
+        }
       if ( ichar == '\n' ) break;
       line[ipos++] = ichar;
       if ( ipos >= len )
@@ -36,5 +41,5 @@ int readline(FILE *fp, char *line, int len)
 
   if ( feof(fp) && ipos == 0 ) return 0;
 
-  return (1);
+  return 1;
 }
diff --git a/src/remap.h b/src/remap.h
index 92a979f..ff8bb84 100644
--- a/src/remap.h
+++ b/src/remap.h
@@ -73,17 +73,19 @@ typedef RESTR_TYPE restr_t;
 
 
 typedef struct {
-  int      lwrite_remap;
   int      gridID;
-  int      store_link_fast;
   int      remap_grid_type;
-  int      lextrapolate;
-  int      non_global;
-  int      is_cyclic;
   int      rank;                  /* rank of the grid */
   long     size;                  /* total points on the grid */
   long     num_cell_corners;      /* number of corners for each grid cell */
 
+  bool     lneed_cell_corners;
+  bool     luse_cell_corners;     /* use corners for bounding boxes  */
+
+  bool     lextrapolate;
+  bool     non_global;
+  bool     is_cyclic;
+
   int      dims[2];               /* size of grid dimension */
 
   int      nvgp;                  /* size of vgpm           */
@@ -104,9 +106,6 @@ typedef struct {
   double*  cell_area;             /* tot area of each grid cell     */
   double*  cell_frac;             /* fractional area of grid cells participating in remapping  */
 
-  int      lneed_cell_corners;
-  int      luse_cell_corners;     /* use corners for bounding boxes  */
-
   restr_t *cell_bound_box;        /* lon/lat bounding box for use    */
 
   int      num_srch_bins;         /* num of bins for restricted srch */
@@ -168,7 +167,7 @@ void remap_set_threshhold(double threshhold);
 void remap_set_int(int remapvar, int value);
 
 
-void remap_grids_init(int map_type, int lextrapolate, int gridID1, remapgrid_t *src_grid, int gridID2, remapgrid_t *tgt_grid);
+void remap_grids_init(int map_type, bool lextrapolate, int gridID1, remapgrid_t *src_grid, int gridID2, remapgrid_t *tgt_grid);
 void remap_vars_init(int map_type, long src_grid_size, long tgt_grid_size, remapvars_t *rv);
 
 void remapVarsFree(remapvars_t *rv);
diff --git a/src/remap_conserv.c b/src/remap_conserv.c
index 7055407..113f804 100644
--- a/src/remap_conserv.c
+++ b/src/remap_conserv.c
@@ -35,10 +35,10 @@ void search_realloc(long num_srch_cells, search_t *search)
 
   if ( num_srch_cells > max_srch_cells )
     {
-      partial_areas   = (double*) realloc(partial_areas,   num_srch_cells*sizeof(double));
-      partial_weights = (double*) realloc(partial_weights, num_srch_cells*sizeof(double));
-      overlap_buffer = (struct grid_cell*) realloc(overlap_buffer, num_srch_cells*sizeof(struct grid_cell));
-      src_grid_cells = (struct grid_cell*) realloc(src_grid_cells, num_srch_cells*sizeof(struct grid_cell));
+      partial_areas   = (double*) Realloc(partial_areas,   num_srch_cells*sizeof(double));
+      partial_weights = (double*) Realloc(partial_weights, num_srch_cells*sizeof(double));
+      overlap_buffer = (struct grid_cell*) Realloc(overlap_buffer, num_srch_cells*sizeof(struct grid_cell));
+      src_grid_cells = (struct grid_cell*) Realloc(src_grid_cells, num_srch_cells*sizeof(struct grid_cell));
 
       for ( long n = max_srch_cells; n < num_srch_cells; ++n )
         {
@@ -55,9 +55,9 @@ void search_realloc(long num_srch_cells, search_t *search)
           src_grid_cells[n].array_size      = search->srch_corners;
           src_grid_cells[n].num_corners     = search->srch_corners;
           src_grid_cells[n].edge_type       = search->src_edge_type;
-          src_grid_cells[n].coordinates_x   = (double*) malloc(search->srch_corners*sizeof(double));
-          src_grid_cells[n].coordinates_y   = (double*) malloc(search->srch_corners*sizeof(double));
-          src_grid_cells[n].coordinates_xyz = (double*) malloc(3*search->srch_corners*sizeof(double));
+          src_grid_cells[n].coordinates_x   = (double*) Malloc(search->srch_corners*sizeof(double));
+          src_grid_cells[n].coordinates_y   = (double*) Malloc(search->srch_corners*sizeof(double));
+          src_grid_cells[n].coordinates_xyz = (double*) Malloc(3*search->srch_corners*sizeof(double));
         }
 
       max_srch_cells = num_srch_cells;
@@ -608,9 +608,9 @@ void remapNormalizeWeights(remapgrid_t *tgt_grid, remapvars_t *rv)
 	  tgt_cell_add = rv->tgt_cell_add[n];
 
           if ( IS_NOT_EQUAL(tgt_grid->cell_area[tgt_cell_add], 0) )
-	    norm_factor = ONE/tgt_grid->cell_area[tgt_cell_add];
+	    norm_factor = 1./tgt_grid->cell_area[tgt_cell_add];
           else
-            norm_factor = ZERO;
+            norm_factor = 0.;
 
 	  rv->wts[n*num_wts] *= norm_factor;
 	}
@@ -630,9 +630,9 @@ void remapNormalizeWeights(remapgrid_t *tgt_grid, remapvars_t *rv)
 	  tgt_cell_add = rv->tgt_cell_add[n];
 
           if ( IS_NOT_EQUAL(tgt_grid->cell_frac[tgt_cell_add], 0) )
-	    norm_factor = ONE/tgt_grid->cell_frac[tgt_cell_add];
+	    norm_factor = 1./tgt_grid->cell_frac[tgt_cell_add];
           else
-            norm_factor = ZERO;
+            norm_factor = 0.;
 
 	  rv->wts[n*num_wts] *= norm_factor;
 	}
diff --git a/src/remap_conserv_scrip.c b/src/remap_conserv_scrip.c
index 9ecfa3f..da7795c 100644
--- a/src/remap_conserv_scrip.c
+++ b/src/remap_conserv_scrip.c
@@ -1569,8 +1569,8 @@ void scrip_remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
 
   for ( i = 0; i < ompNumThreads; ++i )
     {
-      Free(srch_corner_lon2[i]);
-      Free(srch_corner_lat2[i]);
+      free(srch_corner_lon2[i]);
+      free(srch_corner_lat2[i]);
     }
 
   for ( i = 0; i < ompNumThreads; ++i )
@@ -1795,8 +1795,8 @@ void scrip_remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
 
   for ( i = 0; i < ompNumThreads; ++i )
     {
-      Free(srch_corner_lon2[i]);
-      Free(srch_corner_lat2[i]);
+      free(srch_corner_lon2[i]);
+      free(srch_corner_lat2[i]);
     }
 
   for ( i = 0; i < ompNumThreads; ++i )
diff --git a/src/remap_distwgt.c b/src/remap_distwgt.c
index 4bfbcf6..0791afc 100644
--- a/src/remap_distwgt.c
+++ b/src/remap_distwgt.c
@@ -45,18 +45,9 @@ void nbr_store_distance(int nadd, double distance, int num_neighbors, int *restr
 static
 void nbr_check_distance(unsigned num_neighbors, const int *restrict nbr_add, double *restrict nbr_dist)
 {
-  double distance;
-
   // If distance is zero, set to small number
   for ( unsigned nchk = 0; nchk < num_neighbors; ++nchk )
-    {
-      if ( nbr_add[nchk] >= 0 )
-	{
-	  distance = nbr_dist[nchk];
-	  if ( IS_EQUAL(distance, 0.) ) distance = TINY;
-	  nbr_dist[nchk] = distance;
-	}
-    }
+    if ( nbr_add[nchk] >= 0 && nbr_dist[nchk] <= 0. ) nbr_dist[nchk] = TINY;
 }
 
 
@@ -74,8 +65,8 @@ double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_
           if ( nbr_add[n] >= 0 )
             if ( src_grid_mask[nbr_add[n]] )
               {
-                nbr_dist[n] = ONE/nbr_dist[n];
-                dist_tot = dist_tot + nbr_dist[n];
+                nbr_dist[n] = 1./nbr_dist[n];
+                dist_tot += nbr_dist[n];
                 nbr_mask[n] = TRUE;
               }
         }
@@ -87,8 +78,8 @@ double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_
           nbr_mask[n] = FALSE;
           if ( nbr_add[n] >= 0 )
             {
-              nbr_dist[n] = ONE/nbr_dist[n];
-              dist_tot = dist_tot + nbr_dist[n];
+              nbr_dist[n] = 1./nbr_dist[n];
+              dist_tot += nbr_dist[n];
               nbr_mask[n] = TRUE;
             }
         }
@@ -117,20 +108,6 @@ unsigned nbr_normalize_weights(unsigned num_neighbors, double dist_tot, const in
   return nadds;
 }
 
-static
-double get_search_radius(void)
-{
-  extern double gridsearch_radius;
-
-  double search_radius = gridsearch_radius;
-
-  if ( search_radius <    0. ) search_radius = 0.;
-  if ( search_radius >  180. ) search_radius = 180.;
-
-  search_radius = search_radius*DEG2RAD;
-
-  return search_radius;
-}
 
 //  This routine finds the closest num_neighbor points to a search point and computes a distance to each of the neighbors.
 
@@ -159,7 +136,7 @@ void grid_search_nbr_reg2d(struct gridsearch *gs, int num_neighbors, remapgrid_t
   int *psrc_add = src_add;
   int num_add = 0;
   double distance;   //  Angular distance
-  double cos_search_radius = cos(get_search_radius());
+  double cos_search_radius = cos(gs->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
@@ -190,7 +167,7 @@ void grid_search_nbr_reg2d(struct gridsearch *gs, int num_neighbors, remapgrid_t
       for ( k = 3; k < 10000; k+=2 )
         if ( num_neighbors <= ((k-2)*(k-2)) ) break;
 
-      if ( (k*k) > MAX_SEARCH_CELLS ) psrc_add = src_add_tmp = (int *) malloc(k*k*sizeof(int));
+      if ( (k*k) > MAX_SEARCH_CELLS ) psrc_add = src_add_tmp = (int *) Malloc(k*k*sizeof(int));
 
       k /= 2;
 
@@ -254,7 +231,7 @@ void grid_search_nbr_reg2d(struct gridsearch *gs, int num_neighbors, remapgrid_t
 
       nbr_check_distance(num_neighbors, nbr_add, nbr_dist);
 
-      if ( src_add_tmp ) free(src_add_tmp);
+      if ( src_add_tmp ) Free(src_add_tmp);
     }
   else if ( src_grid->lextrapolate )
     {
@@ -283,7 +260,7 @@ void grid_search_nbr_reg2d(struct gridsearch *gs, int num_neighbors, remapgrid_t
 } // grid_search_nbr_reg2d
 
 
-void grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr_add, double *restrict nbr_dist, double plon, double plat)
+int grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr_add, double *restrict nbr_dist, double plon, double plat)
 {
   /*
     Output variables:
@@ -297,19 +274,29 @@ void grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr
     double plon,         ! longitude of the search point
   */
 
-  double search_radius = get_search_radius();
+  double search_radius = gs->search_radius;
 
   // Initialize distance and address arrays
   for ( int n = 0; n < num_neighbors; ++n ) nbr_add[n]  = -1;
   for ( int n = 0; n < num_neighbors; ++n ) nbr_dist[n] = BIGNUM;
 
   int ndist = num_neighbors;
-  ndist = ndist*2; // check some more points if distance is the same use the smaller index (nadd)
+  // check some more points if distance is the same use the smaller index (nadd)
+  if ( ndist > 8 ) ndist += 8;
+  else             ndist *= 2; 
   if ( ndist > (int)gs->n ) ndist = gs->n;
-  double dist[ndist];
-  int    adds[ndist];
 
-  const double range0 = SQR(2*search_radius);
+  double zdist[32];
+  int zadds[32];
+  double *dist = zdist;
+  int *adds = zadds;
+  if ( num_neighbors > 16 )
+    {
+      dist = (double*) Malloc(ndist*sizeof(double));
+      adds = (int*) Malloc(ndist*sizeof(int));
+    }
+  
+  const double range0 = SQR(search_radius);
   double range = range0;
 
   int j = 0;
@@ -339,7 +326,7 @@ void grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr
               nadd  = p->node->index;
               range = p->dist_sq;
               Free(p); // Free the result node taken from the heap
-              
+
               if ( range < range0 )
                 {
                   dist[j] = sqrt(range);
@@ -351,14 +338,24 @@ void grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr
           Free(gs_result);    // and free the heap information structure
         }
     }
-  
+
   ndist = j;
+  int max_neighbors = ( ndist < num_neighbors ) ? ndist : num_neighbors;
 
   for ( j = 0; j < ndist; ++j )
-    nbr_store_distance(adds[j], dist[j], num_neighbors, nbr_add, nbr_dist);
+    nbr_store_distance(adds[j], dist[j], max_neighbors, nbr_add, nbr_dist);
+
+  nbr_check_distance(max_neighbors, nbr_add, nbr_dist);
+
+  if ( num_neighbors > 16 )
+    {
+      Free(dist);
+      Free(adds);
+    }
 
-  nbr_check_distance(num_neighbors, nbr_add, nbr_dist);
+  if ( ndist > num_neighbors ) ndist = num_neighbors;
 
+  return ndist;
 } // grid_search_nbr
 
 //  This routine computes the inverse-distance weights for a nearest-neighbor interpolation.
@@ -377,7 +374,7 @@ void remap_distwgt_weights(unsigned num_neighbors, remapgrid_t *src_grid, remapg
   unsigned tgt_grid_size = tgt_grid->size;
   unsigned nx = src_grid->dims[0];
   unsigned ny = src_grid->dims[1];
-  unsigned lcyclic = src_grid->is_cyclic;
+  bool lcyclic = src_grid->is_cyclic;
 
   weightlinks_t *weightlinks = (weightlinks_t *) Malloc(tgt_grid_size*sizeof(weightlinks_t));
   weightlinks[0].addweights = (addweight_t *) Malloc(num_neighbors*tgt_grid_size*sizeof(addweight_t));
@@ -485,7 +482,7 @@ void remap_distwgt(unsigned num_neighbors, remapgrid_t *src_grid, remapgrid_t *t
   unsigned tgt_grid_size = tgt_grid->size;
   unsigned nx = src_grid->dims[0];
   unsigned ny = src_grid->dims[1];
-  unsigned lcyclic = src_grid->is_cyclic;
+  bool lcyclic = src_grid->is_cyclic;
 
   int nbr_mask[num_neighbors];    // mask at nearest neighbors
   int nbr_add[num_neighbors];     // source address at nearest neighbors
diff --git a/src/remap_scrip_io.c b/src/remap_scrip_io.c
index 372576f..fcea19c 100644
--- a/src/remap_scrip_io.c
+++ b/src/remap_scrip_io.c
@@ -579,8 +579,8 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
     {
       nce(nc_inq_dimlen(nc_file_id, nc_srcgrdcorn_id, &dimlen));
       src_grid->num_cell_corners = dimlen;
-      src_grid->luse_cell_corners = TRUE;
-      src_grid->lneed_cell_corners = TRUE;
+      src_grid->luse_cell_corners = true;
+      src_grid->lneed_cell_corners = true;
     }
 
   status = nc_inq_dimid(nc_file_id, "dst_grid_corners", &nc_dstgrdcorn_id);
@@ -588,8 +588,8 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
     {
       nce(nc_inq_dimlen(nc_file_id, nc_dstgrdcorn_id, &dimlen));
       tgt_grid->num_cell_corners = dimlen;
-      tgt_grid->luse_cell_corners = TRUE;
-      tgt_grid->lneed_cell_corners = TRUE;
+      tgt_grid->luse_cell_corners = true;
+      tgt_grid->lneed_cell_corners = true;
     }
 
   nce(nc_inq_dimid(nc_file_id, "src_grid_rank", &nc_srcgrdrank_id));
diff --git a/src/remaplib.c b/src/remaplib.c
index 1c45eb2..10da6fb 100644
--- a/src/remaplib.c
+++ b/src/remaplib.c
@@ -155,8 +155,8 @@ void remapgrid_init(remapgrid_t *grid)
   grid->num_srch_bins    = remap_num_srch_bins; // only for source grid ?
 
   grid->num_cell_corners = 0;
-  grid->luse_cell_corners  = FALSE;
-  grid->lneed_cell_corners = FALSE;
+  grid->luse_cell_corners  = false;
+  grid->lneed_cell_corners = false;
 
   grid->nvgp             = 0;
   grid->vgpm             = NULL;
@@ -263,7 +263,7 @@ void boundbox_from_corners(long size, long nc, const double *restrict corner_lon
 }
 
 static
-void boundbox_from_center(int lonIsCyclic, long size, long nx, long ny, const double *restrict center_lon,
+void boundbox_from_center(bool lonIsCyclic, long size, long nx, long ny, const double *restrict center_lon,
 			  const double *restrict center_lat, restr_t *restrict bound_box)
 {
   long n4, i, j, k, ip1, jp1;
@@ -289,10 +289,7 @@ void boundbox_from_center(int lonIsCyclic, long size, long nx, long ny, const do
       else
 	{
 	  /* 2009-01-09 Uwe Schulzweida: bug fix */
-	  if ( lonIsCyclic )
-	    ip1 = 0;
-	  else
-	    ip1 = i;
+	  ip1 = lonIsCyclic ? 0 : i;
 	}
 
       if ( j < (ny-1) )
@@ -656,7 +653,7 @@ void remap_define_reg2d(int gridID, remapgrid_t *grid)
 }
 
 static
-void remap_define_grid(int map_type, int gridID, remapgrid_t *grid)
+void remap_define_grid(int map_type, int gridID, remapgrid_t *grid, const char *txt)
 {
   char xunitstr[CDI_MAX_NAME];
   char yunitstr[CDI_MAX_NAME];
@@ -674,7 +671,7 @@ void remap_define_grid(int map_type, int gridID, remapgrid_t *grid)
 	  grid->nvgp = gridInqSize(gridID_gme);
 	  gridID = gridDuplicate(gridID_gme);
 	  gridCompress(gridID);
-	  grid->luse_cell_corners = TRUE;
+	  grid->luse_cell_corners = true;
 	}
       else if ( remap_write_remap == TRUE || grid->remap_grid_type != REMAP_GRID_TYPE_REG2D )
 	{
@@ -694,7 +691,7 @@ void remap_define_grid(int map_type, int gridID, remapgrid_t *grid)
       if ( grid->dims[1] == 0 ) cdoAbort("%s grid without latitude coordinates!", gridNamePtr(gridInqType(grid->gridID)));
     }
 
-  grid->is_cyclic = gridIsCircular(gridID);
+  grid->is_cyclic = gridIsCircular(gridID) ? true : false;
 
   if ( gridInqType(gridID) == GRID_UNSTRUCTURED )
     grid->rank = 1;
@@ -727,7 +724,7 @@ void remap_define_grid(int map_type, int gridID, remapgrid_t *grid)
   if ( remap_write_remap == FALSE && grid->remap_grid_type == REMAP_GRID_TYPE_REG2D ) return;
 
   if ( !(gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL)) )
-    cdoAbort("Grid cell center coordinates missing!");
+    cdoAbort("%s grid cell center coordinates missing!", txt);
 
   gridInqXvals(gridID, grid->cell_center_lon);
   gridInqYvals(gridID, grid->cell_center_lat);
@@ -750,7 +747,7 @@ void remap_define_grid(int map_type, int gridID, remapgrid_t *grid)
 	}
       else
 	{
-	  cdoAbort("Grid cell corner coordinates missing!");
+	  cdoAbort("%s grid cell corner coordinates missing!", txt);
 	}
     }
 
@@ -847,7 +844,7 @@ void cell_bounding_boxes(remapgrid_t *grid, int remap_grid_basis)
 }
 
 
-void remap_grids_init(int map_type, int lextrapolate, int gridID1, remapgrid_t *src_grid, int gridID2, remapgrid_t *tgt_grid)
+void remap_grids_init(int map_type, bool lextrapolate, int gridID1, remapgrid_t *src_grid, int gridID2, remapgrid_t *tgt_grid)
 {
   int lbounds = TRUE;
   int reg2d_src_gridID = gridID1;
@@ -876,23 +873,23 @@ void remap_grids_init(int map_type, int lextrapolate, int gridID1, remapgrid_t *
       if ( map_type == MAP_TYPE_BILINEAR && src_grid->remap_grid_type == REMAP_GRID_TYPE_REG2D ) tgt_grid->remap_grid_type = REMAP_GRID_TYPE_REG2D;
     }
 
-  if ( lextrapolate > 0 )
-    src_grid->lextrapolate = TRUE;
+  if ( lextrapolate )
+    src_grid->lextrapolate = true;
   else
-    src_grid->lextrapolate = FALSE;
+    src_grid->lextrapolate = false;
 
   if ( map_type == MAP_TYPE_CONSERV || map_type == MAP_TYPE_CONSERV_YAC )
     {
       if ( src_grid->remap_grid_type != REMAP_GRID_TYPE_REG2D )
 	{
-	  src_grid->luse_cell_corners  = TRUE;
-	  src_grid->lneed_cell_corners = TRUE;
+	  src_grid->luse_cell_corners  = true;
+	  src_grid->lneed_cell_corners = true;
 	}
 
       if ( tgt_grid->remap_grid_type != REMAP_GRID_TYPE_REG2D )
 	{
-	  tgt_grid->luse_cell_corners  = TRUE;
-	  tgt_grid->lneed_cell_corners = TRUE;
+	  tgt_grid->luse_cell_corners  = true;
+	  tgt_grid->lneed_cell_corners = true;
 	}
     }
 
@@ -948,9 +945,9 @@ void remap_grids_init(int map_type, int lextrapolate, int gridID1, remapgrid_t *
     }
 
   //if ( src_grid->remap_grid_type != REMAP_GRID_TYPE_REG2D )
-    remap_define_grid(map_type, gridID1, src_grid);
+  remap_define_grid(map_type, gridID1, src_grid, "Source");
 
-  remap_define_grid(map_type, gridID2, tgt_grid);
+  remap_define_grid(map_type, gridID2, tgt_grid, "Target");
 
   if ( src_grid->remap_grid_type == REMAP_GRID_TYPE_REG2D && tgt_grid->remap_grid_type == REMAP_GRID_TYPE_REG2D )
     {
diff --git a/src/remapsort.c b/src/remapsort.c
index e3b072e..53f6211 100644
--- a/src/remapsort.c
+++ b/src/remapsort.c
@@ -113,7 +113,7 @@ void remap_heapsort(const long num_links, int *restrict add1, int *restrict add2
 
       /* Loop until proper level is found for this link, or reach bottom */
 
-      for ( i = 0; i < num_links; ++i ) /* while ( TRUE ) */
+      for ( i = 0; i < num_links; ++i )
 	{
 	  /* Find the largest of the two daughters */
 
@@ -190,7 +190,7 @@ void remap_heapsort(const long num_links, int *restrict add1, int *restrict add2
 
       final_lvl = 0;
 
-      for ( i = 0; i < num_links; ++i ) /* while ( TRUE ) */
+      for ( i = 0; i < num_links; ++i )
 	{
 	  /* Find the largest of the two daughters */
 
@@ -352,7 +352,7 @@ void sort_add_orig(long num_links, long num_wts, int *restrict add1, int *restri
 
       /* Loop until proper level is found for this link, or reach bottom */
 
-      for ( i = 0; i < num_links; i++ ) /* while ( TRUE ) */
+      for ( i = 0; i < num_links; i++ )
 	{
 	  /* Find the largest of the two daughters */
 
@@ -435,7 +435,7 @@ void sort_add_orig(long num_links, long num_wts, int *restrict add1, int *restri
 
       final_lvl = 0;
 
-      for ( i = 0; i < num_links; i++ ) /* while ( TRUE ) */
+      for ( i = 0; i < num_links; i++ )
 	{
 	  /* Find the largest of the two daughters */
 
diff --git a/src/userlog.c b/src/userlog.c
index 1317ce3..2aef1f9 100644
--- a/src/userlog.c
+++ b/src/userlog.c
@@ -147,10 +147,13 @@ void cdolog(const char *prompt, double cputime)
   close(logfileno);
 
   errno = 0;
-
-  return;
-
+#else
+  UNUSED(prompt);
+  UNUSED(cputime);
 #endif
+#else
+  UNUSED(prompt);
+  UNUSED(cputime);
 #endif
 }
 
@@ -442,9 +445,8 @@ void cdologs(int noper)
   close(logfileno);
 
   errno = 0;
-
-  return;
-
+#else
+  UNUSED(noper);
 #endif
 #endif
 }
@@ -523,15 +525,13 @@ void dumplogs(const char *logfilename)
   close(logfileno);
 
   errno = 0;
-
-  return;
 #endif
 }
 
 
 void daylogs(const char *logfilename)
 {
-  int  logfileno;
+  int logfileno;
   int status;
   int date0 = 0, ncdo0, noper0, nhours0;
   int nlogs;
@@ -550,6 +550,8 @@ void daylogs(const char *logfilename)
   size_t bufsize;
   struct stat filestat;
 
+  UNUSED(ncdo0);
+
   errno = 0;
   logfileno = open(logfilename, O_RDONLY);
   if ( errno )
@@ -593,8 +595,6 @@ void daylogs(const char *logfilename)
   close(logfileno);
 
   errno = 0;
-
-  return;
 }
 
 
@@ -622,6 +622,8 @@ void monlogs(const char *logfilename)
   size_t bufsize;
   struct stat filestat;
 
+  UNUSED(ncdo0);
+  
   errno = 0;
   logfileno = open(logfilename, O_RDONLY);
   if ( errno )
@@ -683,8 +685,6 @@ void monlogs(const char *logfilename)
   close(logfileno);
 
   errno = 0;
-
-  return;
 }
 
 
@@ -829,9 +829,8 @@ void cdologo(int noper)
   close(logfileno);
 
   errno = 0;
-
-  return;
-
+#else
+  UNUSED(noper);
 #endif
 #endif
 }
@@ -857,7 +856,7 @@ int cmplognocc(const void *s1, const void *s2)
   if      ( x->nocc < y->nocc ) cmp =  1;
   else if ( x->nocc > y->nocc ) cmp = -1;
 
-  return (cmp);
+  return cmp;
 }
 
 static
@@ -870,7 +869,7 @@ int cmplognvals(const void *s1, const void *s2)
   if      ( x->nvals < y->nvals ) cmp =  1;
   else if ( x->nvals > y->nvals ) cmp = -1;
 
-  return (cmp);
+  return cmp;
 }
 
 static
@@ -883,7 +882,7 @@ int cmplogtime(const void *s1, const void *s2)
   if      ( x->time < y->time ) cmp =  1;
   else if ( x->time > y->time ) cmp = -1;
 
-  return (cmp);
+  return cmp;
 }
 
 static
@@ -896,7 +895,7 @@ int cmplogperc(const void *s1, const void *s2)
   if      ( x->perc < y->perc ) cmp =  1;
   else if ( x->perc > y->perc ) cmp = -1;
 
-  return (cmp);
+  return cmp;
 }
 
 static
@@ -905,7 +904,7 @@ int cmplogname(const void *s1, const void *s2)
   const loginfo_t *x = (const loginfo_t *)s1;
   const loginfo_t *y = (const loginfo_t *)s2;
 
-  return (strcmp(x->name, y->name));
+  return strcmp(x->name, y->name);
 }
 
 
@@ -1011,7 +1010,5 @@ void dumplogo(const char *logfilename, int dumptype)
   close(logfileno);
 
   errno = 0;
-
-  return;
 #endif
 }
diff --git a/src/uthash.h b/src/uthash.h
new file mode 100644
index 0000000..ed69c0c
--- /dev/null
+++ b/src/uthash.h
@@ -0,0 +1,966 @@
+/*
+Copyright (c) 2003-2014, Troy D. Hanson     http://troydhanson.github.com/uthash/
+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.
+
+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.
+*/
+
+#ifndef UTHASH_H
+#define UTHASH_H
+
+#include <string.h>   /* memcmp,strlen */
+#include <stddef.h>   /* ptrdiff_t */
+#include <stdlib.h>   /* exit() */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+   As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+   when compiling c++ source) this code uses whatever method is needed
+   or, for VS2008 where neither is available, uses casting workarounds. */
+#if defined(_MSC_VER)   /* MS compiler */
+#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
+#define DECLTYPE(x) (decltype(x))
+#else                   /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define DECLTYPE(x)
+#endif
+#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)
+#define NO_DECLTYPE
+#define DECLTYPE(x)
+#else                   /* GNU, Sun and other compilers */
+#define DECLTYPE(x) (__typeof(x))
+#endif
+
+#ifdef NO_DECLTYPE
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  char **_da_dst = (char**)(&(dst));                                             \
+  *_da_dst = (char*)(src);                                                       \
+} while(0)
+#else
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  (dst) = DECLTYPE(dst)(src);                                                    \
+} while(0)
+#endif
+
+/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
+#if defined(_WIN32)
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+#include <stdint.h>
+#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
+#include <stdint.h>
+#else
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+#endif
+#elif defined(__GNUC__) && !defined(__VXWORKS__)
+#include <stdint.h>
+#else
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+#endif
+
+#define UTHASH_VERSION 1.9.9
+
+#ifndef uthash_fatal
+#define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */
+#endif
+#ifndef uthash_malloc
+#define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */
+#endif
+#ifndef uthash_free
+#define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */
+#endif
+
+#ifndef uthash_noexpand_fyi
+#define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */
+#endif
+#ifndef uthash_expand_fyi
+#define uthash_expand_fyi(tbl)            /* can be defined to log expands   */
+#endif
+
+/* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS 32U     /* initial number of buckets        */
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */
+#define HASH_BKT_CAPACITY_THRESH 10U     /* expand when bucket count reaches */
+
+/* calculate the element whose hash handle address is hhe */
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
+
+#define HASH_FIND(hh,head,keyptr,keylen,out)                                     \
+do {                                                                             \
+  out=NULL;                                                                      \
+  if (head != NULL) {                                                            \
+     unsigned _hf_bkt,_hf_hashv;                                                 \
+     HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt);   \
+     if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv) != 0) {                      \
+       HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ],  \
+                        keyptr,keylen,out);                                      \
+     }                                                                           \
+  }                                                                              \
+} while (0)
+
+#ifdef HASH_BLOOM
+#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM)
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL)
+#define HASH_BLOOM_MAKE(tbl)                                                     \
+do {                                                                             \
+  (tbl)->bloom_nbits = HASH_BLOOM;                                               \
+  (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \
+  if (!((tbl)->bloom_bv))  { uthash_fatal( "out of memory"); }                   \
+  memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \
+  (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \
+} while (0)
+
+#define HASH_BLOOM_FREE(tbl)                                                     \
+do {                                                                             \
+  uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \
+} while (0)
+
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
+
+#define HASH_BLOOM_ADD(tbl,hashv)                                                \
+  HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))
+
+#define HASH_BLOOM_TEST(tbl,hashv)                                               \
+  HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))
+
+#else
+#define HASH_BLOOM_MAKE(tbl)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
+#define HASH_BLOOM_BYTELEN 0U
+#endif
+
+#define HASH_MAKE_TABLE(hh,head)                                                 \
+do {                                                                             \
+  (head)->hh.tbl = (UT_hash_table*)uthash_malloc(                                \
+                  sizeof(UT_hash_table));                                        \
+  if (!((head)->hh.tbl))  { uthash_fatal( "out of memory"); }                    \
+  memset((head)->hh.tbl, 0, sizeof(UT_hash_table));                              \
+  (head)->hh.tbl->tail = &((head)->hh);                                          \
+  (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                        \
+  (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;              \
+  (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                    \
+  (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                      \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); }             \
+  memset((head)->hh.tbl->buckets, 0,                                             \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  HASH_BLOOM_MAKE((head)->hh.tbl);                                               \
+  (head)->hh.tbl->signature = HASH_SIGNATURE;                                    \
+} while(0)
+
+#define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
+        HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
+
+#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced)                   \
+do {                                                                             \
+  replaced=NULL;                                                                 \
+  HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced);                     \
+  if (replaced!=NULL) {                                                          \
+     HASH_DELETE(hh,head,replaced);                                              \
+  }                                                                              \
+  HASH_ADD(hh,head,fieldname,keylen_in,add);                                     \
+} while(0)
+
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
+do {                                                                             \
+ unsigned _ha_bkt;                                                               \
+ (add)->hh.next = NULL;                                                          \
+ (add)->hh.key = (char*)(keyptr);                                                \
+ (add)->hh.keylen = (unsigned)(keylen_in);                                       \
+ if (!(head)) {                                                                  \
+    head = (add);                                                                \
+    (head)->hh.prev = NULL;                                                      \
+    HASH_MAKE_TABLE(hh,head);                                                    \
+ } else {                                                                        \
+    (head)->hh.tbl->tail->next = (add);                                          \
+    (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);         \
+    (head)->hh.tbl->tail = &((add)->hh);                                         \
+ }                                                                               \
+ (head)->hh.tbl->num_items++;                                                    \
+ (add)->hh.tbl = (head)->hh.tbl;                                                 \
+ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets,                         \
+         (add)->hh.hashv, _ha_bkt);                                              \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh);                   \
+ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv);                                 \
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in);                                        \
+ HASH_FSCK(hh,head);                                                             \
+} while(0)
+
+#define HASH_TO_BKT( hashv, num_bkts, bkt )                                      \
+do {                                                                             \
+  bkt = ((hashv) & ((num_bkts) - 1U));                                           \
+} while(0)
+
+/* delete "delptr" from the hash table.
+ * "the usual" patch-up process for the app-order doubly-linked-list.
+ * The use of _hd_hh_del below deserves special explanation.
+ * These used to be expressed using (delptr) but that led to a bug
+ * if someone used the same symbol for the head and deletee, like
+ *  HASH_DELETE(hh,users,users);
+ * We want that to work, but by changing the head (users) below
+ * we were forfeiting our ability to further refer to the deletee (users)
+ * in the patch-up process. Solution: use scratch space to
+ * copy the deletee pointer, then the latter references are via that
+ * scratch pointer rather than through the repointed (users) symbol.
+ */
+#define HASH_DELETE(hh,head,delptr)                                              \
+do {                                                                             \
+    struct UT_hash_handle *_hd_hh_del;                                           \
+    if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) )  {         \
+        uthash_free((head)->hh.tbl->buckets,                                     \
+                    (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+        HASH_BLOOM_FREE((head)->hh.tbl);                                         \
+        uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                      \
+        head = NULL;                                                             \
+    } else {                                                                     \
+        unsigned _hd_bkt;                                                        \
+        _hd_hh_del = &((delptr)->hh);                                            \
+        if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
+            (head)->hh.tbl->tail =                                               \
+                (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +               \
+                (head)->hh.tbl->hho);                                            \
+        }                                                                        \
+        if ((delptr)->hh.prev != NULL) {                                         \
+            ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +                  \
+                    (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \
+        } else {                                                                 \
+            DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \
+        }                                                                        \
+        if (_hd_hh_del->next != NULL) {                                          \
+            ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next +                     \
+                    (head)->hh.tbl->hho))->prev =                                \
+                    _hd_hh_del->prev;                                            \
+        }                                                                        \
+        HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);   \
+        HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);        \
+        (head)->hh.tbl->num_items--;                                             \
+    }                                                                            \
+    HASH_FSCK(hh,head);                                                          \
+} while (0)
+
+
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
+#define HASH_FIND_STR(head,findstr,out)                                          \
+    HASH_FIND(hh,head,findstr,(unsigned)strlen(findstr),out)
+#define HASH_ADD_STR(head,strfield,add)                                          \
+    HASH_ADD(hh,head,strfield[0],(unsigned int)strlen(add->strfield),add)
+#define HASH_REPLACE_STR(head,strfield,add,replaced)                             \
+    HASH_REPLACE(hh,head,strfield[0],(unsigned)strlen(add->strfield),add,replaced)
+#define HASH_FIND_INT(head,findint,out)                                          \
+    HASH_FIND(hh,head,findint,sizeof(int),out)
+#define HASH_ADD_INT(head,intfield,add)                                          \
+    HASH_ADD(hh,head,intfield,sizeof(int),add)
+#define HASH_REPLACE_INT(head,intfield,add,replaced)                             \
+    HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
+#define HASH_FIND_PTR(head,findptr,out)                                          \
+    HASH_FIND(hh,head,findptr,sizeof(void *),out)
+#define HASH_ADD_PTR(head,ptrfield,add)                                          \
+    HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
+#define HASH_REPLACE_PTR(head,ptrfield,add,replaced)                             \
+    HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
+#define HASH_DEL(head,delptr)                                                    \
+    HASH_DELETE(hh,head,delptr)
+
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
+ */
+#ifdef HASH_DEBUG
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
+#define HASH_FSCK(hh,head)                                                       \
+do {                                                                             \
+    struct UT_hash_handle *_thh;                                                 \
+    if (head) {                                                                  \
+        unsigned _bkt_i;                                                         \
+        unsigned _count;                                                         \
+        char *_prev;                                                             \
+        _count = 0;                                                              \
+        for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) {       \
+            unsigned _bkt_count = 0;                                             \
+            _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                      \
+            _prev = NULL;                                                        \
+            while (_thh) {                                                       \
+               if (_prev != (char*)(_thh->hh_prev)) {                            \
+                   HASH_OOPS("invalid hh_prev %p, actual %p\n",                  \
+                    _thh->hh_prev, _prev );                                      \
+               }                                                                 \
+               _bkt_count++;                                                     \
+               _prev = (char*)(_thh);                                            \
+               _thh = _thh->hh_next;                                             \
+            }                                                                    \
+            _count += _bkt_count;                                                \
+            if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {          \
+               HASH_OOPS("invalid bucket count %u, actual %u\n",                 \
+                (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);              \
+            }                                                                    \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid hh item count %u, actual %u\n",                   \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+        /* traverse hh in app order; check next/prev integrity, count */         \
+        _count = 0;                                                              \
+        _prev = NULL;                                                            \
+        _thh =  &(head)->hh;                                                     \
+        while (_thh) {                                                           \
+           _count++;                                                             \
+           if (_prev !=(char*)(_thh->prev)) {                                    \
+              HASH_OOPS("invalid prev %p, actual %p\n",                          \
+                    _thh->prev, _prev );                                         \
+           }                                                                     \
+           _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                    \
+           _thh = ( _thh->next ?  (UT_hash_handle*)((char*)(_thh->next) +        \
+                                  (head)->hh.tbl->hho) : NULL );                 \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid app item count %u, actual %u\n",                  \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+    }                                                                            \
+} while (0)
+#else
+#define HASH_FSCK(hh,head)
+#endif
+
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
+ * the descriptor to which this macro is defined for tuning the hash function.
+ * The app can #include <unistd.h> to get the prototype for write(2). */
+#ifdef HASH_EMIT_KEYS
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \
+do {                                                                             \
+    unsigned _klen = fieldlen;                                                   \
+    write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \
+    write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen);                      \
+} while (0)
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
+#endif
+
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
+#ifdef HASH_FUNCTION
+#define HASH_FCN HASH_FUNCTION
+#else
+#define HASH_FCN HASH_JEN
+#endif
+
+/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
+#define HASH_BER(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hb_keylen=(unsigned)keylen;                                          \
+  const unsigned char *_hb_key=(const unsigned char*)(key);                      \
+  (hashv) = 0;                                                                   \
+  while (_hb_keylen-- != 0U) {                                                   \
+      (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++;                         \
+  }                                                                              \
+  bkt = (hashv) & (num_bkts-1U);                                                 \
+} while (0)
+
+
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
+#define HASH_SAX(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _sx_i;                                                                \
+  const unsigned char *_hs_key=(const unsigned char*)(key);                      \
+  hashv = 0;                                                                     \
+  for(_sx_i=0; _sx_i < keylen; _sx_i++) {                                        \
+      hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i];                     \
+  }                                                                              \
+  bkt = hashv & (num_bkts-1U);                                                   \
+} while (0)
+/* FNV-1a variation */
+#define HASH_FNV(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _fn_i;                                                                \
+  const unsigned char *_hf_key=(const unsigned char*)(key);                      \
+  hashv = 2166136261U;                                                           \
+  for(_fn_i=0; _fn_i < keylen; _fn_i++) {                                        \
+      hashv = hashv ^ _hf_key[_fn_i];                                            \
+      hashv = hashv * 16777619U;                                                 \
+  }                                                                              \
+  bkt = hashv & (num_bkts-1U);                                                   \
+} while(0)
+
+#define HASH_OAT(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _ho_i;                                                                \
+  const unsigned char *_ho_key=(const unsigned char*)(key);                      \
+  hashv = 0;                                                                     \
+  for(_ho_i=0; _ho_i < keylen; _ho_i++) {                                        \
+      hashv += _ho_key[_ho_i];                                                   \
+      hashv += (hashv << 10);                                                    \
+      hashv ^= (hashv >> 6);                                                     \
+  }                                                                              \
+  hashv += (hashv << 3);                                                         \
+  hashv ^= (hashv >> 11);                                                        \
+  hashv += (hashv << 15);                                                        \
+  bkt = hashv & (num_bkts-1U);                                                   \
+} while(0)
+
+#define HASH_JEN_MIX(a,b,c)                                                      \
+do {                                                                             \
+  a -= b; a -= c; a ^= ( c >> 13 );                                              \
+  b -= c; b -= a; b ^= ( a << 8 );                                               \
+  c -= a; c -= b; c ^= ( b >> 13 );                                              \
+  a -= b; a -= c; a ^= ( c >> 12 );                                              \
+  b -= c; b -= a; b ^= ( a << 16 );                                              \
+  c -= a; c -= b; c ^= ( b >> 5 );                                               \
+  a -= b; a -= c; a ^= ( c >> 3 );                                               \
+  b -= c; b -= a; b ^= ( a << 10 );                                              \
+  c -= a; c -= b; c ^= ( b >> 15 );                                              \
+} while (0)
+
+#define HASH_JEN(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hj_i,_hj_j,_hj_k;                                                    \
+  unsigned const char *_hj_key=(unsigned const char*)(key);                      \
+  hashv = 0xfeedbeefu;                                                           \
+  _hj_i = _hj_j = 0x9e3779b9u;                                                   \
+  _hj_k = (unsigned)(keylen);                                                    \
+  while (_hj_k >= 12U) {                                                         \
+    _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \
+        + ( (unsigned)_hj_key[2] << 16 )                                         \
+        + ( (unsigned)_hj_key[3] << 24 ) );                                      \
+    _hj_j +=    (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 )                      \
+        + ( (unsigned)_hj_key[6] << 16 )                                         \
+        + ( (unsigned)_hj_key[7] << 24 ) );                                      \
+    hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 )                         \
+        + ( (unsigned)_hj_key[10] << 16 )                                        \
+        + ( (unsigned)_hj_key[11] << 24 ) );                                     \
+                                                                                 \
+     HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                          \
+                                                                                 \
+     _hj_key += 12;                                                              \
+     _hj_k -= 12U;                                                               \
+  }                                                                              \
+  hashv += (unsigned)(keylen);                                                   \
+  switch ( _hj_k ) {                                                             \
+     case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */        \
+     case 10: hashv += ( (unsigned)_hj_key[9] << 16 );  /* FALLTHROUGH */        \
+     case 9:  hashv += ( (unsigned)_hj_key[8] << 8 );   /* FALLTHROUGH */        \
+     case 8:  _hj_j += ( (unsigned)_hj_key[7] << 24 );  /* FALLTHROUGH */        \
+     case 7:  _hj_j += ( (unsigned)_hj_key[6] << 16 );  /* FALLTHROUGH */        \
+     case 6:  _hj_j += ( (unsigned)_hj_key[5] << 8 );   /* FALLTHROUGH */        \
+     case 5:  _hj_j += _hj_key[4];                      /* FALLTHROUGH */        \
+     case 4:  _hj_i += ( (unsigned)_hj_key[3] << 24 );  /* FALLTHROUGH */        \
+     case 3:  _hj_i += ( (unsigned)_hj_key[2] << 16 );  /* FALLTHROUGH */        \
+     case 2:  _hj_i += ( (unsigned)_hj_key[1] << 8 );   /* FALLTHROUGH */        \
+     case 1:  _hj_i += _hj_key[0];                                               \
+  }                                                                              \
+  HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                             \
+  bkt = hashv & (num_bkts-1U);                                                   \
+} while(0)
+
+/* The Paul Hsieh hash function */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)             \
+  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)             \
+                       +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+#define HASH_SFH(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned const char *_sfh_key=(unsigned const char*)(key);                     \
+  uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen;                                \
+                                                                                 \
+  unsigned _sfh_rem = _sfh_len & 3U;                                             \
+  _sfh_len >>= 2;                                                                \
+  hashv = 0xcafebabeu;                                                           \
+                                                                                 \
+  /* Main loop */                                                                \
+  for (;_sfh_len > 0U; _sfh_len--) {                                             \
+    hashv    += get16bits (_sfh_key);                                            \
+    _sfh_tmp  = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv;              \
+    hashv     = (hashv << 16) ^ _sfh_tmp;                                        \
+    _sfh_key += 2U*sizeof (uint16_t);                                            \
+    hashv    += hashv >> 11;                                                     \
+  }                                                                              \
+                                                                                 \
+  /* Handle end cases */                                                         \
+  switch (_sfh_rem) {                                                            \
+    case 3: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 16;                                                \
+            hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18;              \
+            hashv += hashv >> 11;                                                \
+            break;                                                               \
+    case 2: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 11;                                                \
+            hashv += hashv >> 17;                                                \
+            break;                                                               \
+    case 1: hashv += *_sfh_key;                                                  \
+            hashv ^= hashv << 10;                                                \
+            hashv += hashv >> 1;                                                 \
+  }                                                                              \
+                                                                                 \
+    /* Force "avalanching" of final 127 bits */                                  \
+    hashv ^= hashv << 3;                                                         \
+    hashv += hashv >> 5;                                                         \
+    hashv ^= hashv << 4;                                                         \
+    hashv += hashv >> 17;                                                        \
+    hashv ^= hashv << 25;                                                        \
+    hashv += hashv >> 6;                                                         \
+    bkt = hashv & (num_bkts-1U);                                                 \
+} while(0)
+
+#ifdef HASH_USING_NO_STRICT_ALIASING
+/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
+ * MurmurHash uses the faster approach only on CPU's where we know it's safe.
+ *
+ * Note the preprocessor built-in defines can be emitted using:
+ *
+ *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
+ *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
+ */
+#if (defined(__i386__) || defined(__x86_64__)  || defined(_M_IX86))
+#define MUR_GETBLOCK(p,i) p[i]
+#else /* non intel */
+#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL)
+#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL)
+#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)
+#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)
+#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
+#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
+#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))
+#else /* assume little endian non-intel */
+#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))
+#endif
+#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) :           \
+                            (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
+                             (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) :  \
+                                                      MUR_ONE_THREE(p))))
+#endif
+#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
+#define MUR_FMIX(_h) \
+do {                 \
+  _h ^= _h >> 16;    \
+  _h *= 0x85ebca6bu; \
+  _h ^= _h >> 13;    \
+  _h *= 0xc2b2ae35u; \
+  _h ^= _h >> 16;    \
+} while(0)
+
+#define HASH_MUR(key,keylen,num_bkts,hashv,bkt)                        \
+do {                                                                   \
+  const uint8_t *_mur_data = (const uint8_t*)(key);                    \
+  const int _mur_nblocks = (int)(keylen) / 4;                          \
+  uint32_t _mur_h1 = 0xf88D5353u;                                      \
+  uint32_t _mur_c1 = 0xcc9e2d51u;                                      \
+  uint32_t _mur_c2 = 0x1b873593u;                                      \
+  uint32_t _mur_k1 = 0;                                                \
+  const uint8_t *_mur_tail;                                            \
+  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \
+  int _mur_i;                                                          \
+  for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) {                   \
+    _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);                        \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+                                                                       \
+    _mur_h1 ^= _mur_k1;                                                \
+    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \
+    _mur_h1 = (_mur_h1*5U) + 0xe6546b64u;                              \
+  }                                                                    \
+  _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4));          \
+  _mur_k1=0;                                                           \
+  switch((keylen) & 3U) {                                              \
+    case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \
+    case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8;  /* FALLTHROUGH */ \
+    case 1: _mur_k1 ^= (uint32_t)_mur_tail[0];                         \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+    _mur_h1 ^= _mur_k1;                                                \
+  }                                                                    \
+  _mur_h1 ^= (uint32_t)(keylen);                                       \
+  MUR_FMIX(_mur_h1);                                                   \
+  hashv = _mur_h1;                                                     \
+  bkt = hashv & (num_bkts-1U);                                         \
+} while(0)
+#endif  /* HASH_USING_NO_STRICT_ALIASING */
+
+/* key comparison function; return 0 if keys equal */
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,(unsigned long)(len))
+
+/* iterate over items in a known bucket to find desired item */
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out)                       \
+do {                                                                             \
+ if (head.hh_head != NULL) { DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); } \
+ else { out=NULL; }                                                              \
+ while (out != NULL) {                                                           \
+    if ((out)->hh.keylen == (keylen_in)) {                                       \
+        if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) { break; }         \
+    }                                                                            \
+    if ((out)->hh.hh_next != NULL) { DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); } \
+    else { out = NULL; }                                                         \
+ }                                                                               \
+} while(0)
+
+/* add an item to a bucket  */
+#define HASH_ADD_TO_BKT(head,addhh)                                              \
+do {                                                                             \
+ head.count++;                                                                   \
+ (addhh)->hh_next = head.hh_head;                                                \
+ (addhh)->hh_prev = NULL;                                                        \
+ if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); }                \
+ (head).hh_head=addhh;                                                           \
+ if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH))          \
+     && ((addhh)->tbl->noexpand != 1U)) {                                        \
+       HASH_EXPAND_BUCKETS((addhh)->tbl);                                        \
+ }                                                                               \
+} while(0)
+
+/* remove an item from a given bucket */
+#define HASH_DEL_IN_BKT(hh,head,hh_del)                                          \
+    (head).count--;                                                              \
+    if ((head).hh_head == hh_del) {                                              \
+      (head).hh_head = hh_del->hh_next;                                          \
+    }                                                                            \
+    if (hh_del->hh_prev) {                                                       \
+        hh_del->hh_prev->hh_next = hh_del->hh_next;                              \
+    }                                                                            \
+    if (hh_del->hh_next) {                                                       \
+        hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \
+    }
+
+/* Bucket expansion has the effect of doubling the number of buckets
+ * and redistributing the items into the new buckets. Ideally the
+ * items will distribute more or less evenly into the new buckets
+ * (the extent to which this is true is a measure of the quality of
+ * the hash function as it applies to the key domain).
+ *
+ * With the items distributed into more buckets, the chain length
+ * (item count) in each bucket is reduced. Thus by expanding buckets
+ * the hash keeps a bound on the chain length. This bounded chain
+ * length is the essence of how a hash provides constant time lookup.
+ *
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
+ * explanation. First, keep in mind that we're calculating the ideal
+ * maximum chain length based on the *new* (doubled) bucket count.
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
+ * Since the ideal chain length is an integer, we want to calculate
+ * ceil(n/b). We don't depend on floating point arithmetic in this
+ * hash, so to calculate ceil(n/b) with integers we could write
+ *
+ *      ceil(n/b) = (n/b) + ((n%b)?1:0)
+ *
+ * and in fact a previous version of this hash did just that.
+ * But now we have improved things a bit by recognizing that b is
+ * always a power of two. We keep its base 2 log handy (call it lb),
+ * so now we can write this with a bit shift and logical AND:
+ *
+ *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
+ *
+ */
+#define HASH_EXPAND_BUCKETS(tbl)                                                 \
+do {                                                                             \
+    unsigned _he_bkt;                                                            \
+    unsigned _he_bkt_i;                                                          \
+    struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                 \
+    UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                \
+    _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                            \
+             2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket));            \
+    if (!_he_new_buckets) { uthash_fatal( "out of memory"); }                    \
+    memset(_he_new_buckets, 0,                                                   \
+            2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket));             \
+    tbl->ideal_chain_maxlen =                                                    \
+       (tbl->num_items >> (tbl->log2_num_buckets+1U)) +                          \
+       (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U);        \
+    tbl->nonideal_items = 0;                                                     \
+    for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++)                \
+    {                                                                            \
+        _he_thh = tbl->buckets[ _he_bkt_i ].hh_head;                             \
+        while (_he_thh != NULL) {                                                \
+           _he_hh_nxt = _he_thh->hh_next;                                        \
+           HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt);           \
+           _he_newbkt = &(_he_new_buckets[ _he_bkt ]);                           \
+           if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) {                \
+             tbl->nonideal_items++;                                              \
+             _he_newbkt->expand_mult = _he_newbkt->count /                       \
+                                        tbl->ideal_chain_maxlen;                 \
+           }                                                                     \
+           _he_thh->hh_prev = NULL;                                              \
+           _he_thh->hh_next = _he_newbkt->hh_head;                               \
+           if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev =     \
+                _he_thh; }                                                       \
+           _he_newbkt->hh_head = _he_thh;                                        \
+           _he_thh = _he_hh_nxt;                                                 \
+        }                                                                        \
+    }                                                                            \
+    uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+    tbl->num_buckets *= 2U;                                                      \
+    tbl->log2_num_buckets++;                                                     \
+    tbl->buckets = _he_new_buckets;                                              \
+    tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ?         \
+        (tbl->ineff_expands+1U) : 0U;                                            \
+    if (tbl->ineff_expands > 1U) {                                               \
+        tbl->noexpand=1;                                                         \
+        uthash_noexpand_fyi(tbl);                                                \
+    }                                                                            \
+    uthash_expand_fyi(tbl);                                                      \
+} while(0)
+
+
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
+/* Note that HASH_SORT assumes the hash handle name to be hh.
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
+#define HASH_SRT(hh,head,cmpfcn)                                                 \
+do {                                                                             \
+  unsigned _hs_i;                                                                \
+  unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \
+  struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \
+  if (head != NULL) {                                                            \
+      _hs_insize = 1;                                                            \
+      _hs_looping = 1;                                                           \
+      _hs_list = &((head)->hh);                                                  \
+      while (_hs_looping != 0U) {                                                \
+          _hs_p = _hs_list;                                                      \
+          _hs_list = NULL;                                                       \
+          _hs_tail = NULL;                                                       \
+          _hs_nmerges = 0;                                                       \
+          while (_hs_p != NULL) {                                                \
+              _hs_nmerges++;                                                     \
+              _hs_q = _hs_p;                                                     \
+              _hs_psize = 0;                                                     \
+              for ( _hs_i = 0; _hs_i  < _hs_insize; _hs_i++ ) {                  \
+                  _hs_psize++;                                                   \
+                  _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ?              \
+                          ((void*)((char*)(_hs_q->next) +                        \
+                          (head)->hh.tbl->hho)) : NULL);                         \
+                  if (! (_hs_q) ) { break; }                                     \
+              }                                                                  \
+              _hs_qsize = _hs_insize;                                            \
+              while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\
+                  if (_hs_psize == 0U) {                                         \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ?          \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) {           \
+                      _hs_e = _hs_p;                                             \
+                      if (_hs_p != NULL){                                        \
+                        _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ?        \
+                                ((void*)((char*)(_hs_p->next) +                  \
+                                (head)->hh.tbl->hho)) : NULL);                   \
+                       }                                                         \
+                      _hs_psize--;                                               \
+                  } else if ((                                                   \
+                      cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
+                             DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
+                             ) <= 0) {                                           \
+                      _hs_e = _hs_p;                                             \
+                      if (_hs_p != NULL){                                        \
+                        _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ?        \
+                               ((void*)((char*)(_hs_p->next) +                   \
+                               (head)->hh.tbl->hho)) : NULL);                    \
+                       }                                                         \
+                      _hs_psize--;                                               \
+                  } else {                                                       \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ?          \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  }                                                              \
+                  if ( _hs_tail != NULL ) {                                      \
+                      _hs_tail->next = ((_hs_e != NULL) ?                        \
+                            ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL);          \
+                  } else {                                                       \
+                      _hs_list = _hs_e;                                          \
+                  }                                                              \
+                  if (_hs_e != NULL) {                                           \
+                  _hs_e->prev = ((_hs_tail != NULL) ?                            \
+                     ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \
+                  }                                                              \
+                  _hs_tail = _hs_e;                                              \
+              }                                                                  \
+              _hs_p = _hs_q;                                                     \
+          }                                                                      \
+          if (_hs_tail != NULL){                                                 \
+            _hs_tail->next = NULL;                                               \
+          }                                                                      \
+          if ( _hs_nmerges <= 1U ) {                                             \
+              _hs_looping=0;                                                     \
+              (head)->hh.tbl->tail = _hs_tail;                                   \
+              DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list));      \
+          }                                                                      \
+          _hs_insize *= 2U;                                                      \
+      }                                                                          \
+      HASH_FSCK(hh,head);                                                        \
+ }                                                                               \
+} while (0)
+
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
+ * hash handle that must be present in the structure. */
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \
+do {                                                                             \
+  unsigned _src_bkt, _dst_bkt;                                                   \
+  void *_last_elt=NULL, *_elt;                                                   \
+  UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \
+  ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \
+  if (src != NULL) {                                                             \
+    for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {     \
+      for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;                \
+          _src_hh != NULL;                                                       \
+          _src_hh = _src_hh->hh_next) {                                          \
+          _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                       \
+          if (cond(_elt)) {                                                      \
+            _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);               \
+            _dst_hh->key = _src_hh->key;                                         \
+            _dst_hh->keylen = _src_hh->keylen;                                   \
+            _dst_hh->hashv = _src_hh->hashv;                                     \
+            _dst_hh->prev = _last_elt;                                           \
+            _dst_hh->next = NULL;                                                \
+            if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; }             \
+            if (dst == NULL) {                                                   \
+              DECLTYPE_ASSIGN(dst,_elt);                                         \
+              HASH_MAKE_TABLE(hh_dst,dst);                                       \
+            } else {                                                             \
+              _dst_hh->tbl = (dst)->hh_dst.tbl;                                  \
+            }                                                                    \
+            HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);    \
+            HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh);            \
+            (dst)->hh_dst.tbl->num_items++;                                      \
+            _last_elt = _elt;                                                    \
+            _last_elt_hh = _dst_hh;                                              \
+          }                                                                      \
+      }                                                                          \
+    }                                                                            \
+  }                                                                              \
+  HASH_FSCK(hh_dst,dst);                                                         \
+} while (0)
+
+#define HASH_CLEAR(hh,head)                                                      \
+do {                                                                             \
+  if (head != NULL) {                                                            \
+    uthash_free((head)->hh.tbl->buckets,                                         \
+                (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \
+    HASH_BLOOM_FREE((head)->hh.tbl);                                             \
+    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \
+    (head)=NULL;                                                                 \
+  }                                                                              \
+} while(0)
+
+#define HASH_OVERHEAD(hh,head)                                                   \
+ ((head != NULL) ? (                                                             \
+ (size_t)(((head)->hh.tbl->num_items   * sizeof(UT_hash_handle))   +             \
+          ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket))   +             \
+           sizeof(UT_hash_table)                                   +             \
+           (HASH_BLOOM_BYTELEN))) : 0U)
+
+#ifdef NO_DECLTYPE
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \
+  (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL)))
+#else
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL));      \
+  (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL)))
+#endif
+
+/* obtain a count of items in the hash */
+#define HASH_COUNT(head) HASH_CNT(hh,head)
+#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U)
+
+typedef struct UT_hash_bucket {
+   struct UT_hash_handle *hh_head;
+   unsigned count;
+
+   /* expand_mult is normally set to 0. In this situation, the max chain length
+    * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
+    * the bucket's chain exceeds this length, bucket expansion is triggered).
+    * However, setting expand_mult to a non-zero value delays bucket expansion
+    * (that would be triggered by additions to this particular bucket)
+    * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
+    * (The multiplier is simply expand_mult+1). The whole idea of this
+    * multiplier is to reduce bucket expansions, since they are expensive, in
+    * situations where we know that a particular bucket tends to be overused.
+    * It is better to let its chain length grow to a longer yet-still-bounded
+    * value, than to do an O(n) bucket expansion too often.
+    */
+   unsigned expand_mult;
+
+} UT_hash_bucket;
+
+/* random signature used only to find hash tables in external analysis */
+#define HASH_SIGNATURE 0xa0111fe1u
+#define HASH_BLOOM_SIGNATURE 0xb12220f2u
+
+typedef struct UT_hash_table {
+   UT_hash_bucket *buckets;
+   unsigned num_buckets, log2_num_buckets;
+   unsigned num_items;
+   struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */
+   ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
+
+   /* in an ideal situation (all buckets used equally), no bucket would have
+    * more than ceil(#items/#buckets) items. that's the ideal chain length. */
+   unsigned ideal_chain_maxlen;
+
+   /* nonideal_items is the number of items in the hash whose chain position
+    * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
+    * hash distribution; reaching them in a chain traversal takes >ideal steps */
+   unsigned nonideal_items;
+
+   /* ineffective expands occur when a bucket doubling was performed, but
+    * afterward, more than half the items in the hash had nonideal chain
+    * positions. If this happens on two consecutive expansions we inhibit any
+    * further expansion, as it's not helping; this happens when the hash
+    * function isn't a good fit for the key domain. When expansion is inhibited
+    * the hash will still work, albeit no longer in constant time. */
+   unsigned ineff_expands, noexpand;
+
+   uint32_t signature; /* used only to find hash tables in external analysis */
+#ifdef HASH_BLOOM
+   uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
+   uint8_t *bloom_bv;
+   uint8_t bloom_nbits;
+#endif
+
+} UT_hash_table;
+
+typedef struct UT_hash_handle {
+   struct UT_hash_table *tbl;
+   void *prev;                       /* prev element in app order      */
+   void *next;                       /* next element in app order      */
+   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
+   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
+   void *key;                        /* ptr to enclosing struct's key  */
+   unsigned keylen;                  /* enclosing struct's key len     */
+   unsigned hashv;                   /* result of hash-fcn(key)        */
+} UT_hash_handle;
+
+#endif /* UTHASH_H */
diff --git a/src/util.c b/src/util.c
index d07e3e4..97aacc0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -194,24 +194,23 @@ char *getProgname(char *string)
   if ( progname == NULL ) progname = string;
   else                    progname++;
 
-  return (progname);
+  return progname;
 }
 
 char *getOperator(const char *argument)
 {
   char *operatorArg = NULL;
-  size_t len;
 
   if ( argument )
     {
-      len = 1 + strlen(argument);
+      size_t len = 1 + strlen(argument);
 
       operatorArg = (char*) Malloc(len);
 
       memcpy(operatorArg, argument, len);
     }
 
-  return (operatorArg);
+  return operatorArg;
 }
 
 char *operatorAlias(char *operatorName);
@@ -239,7 +238,7 @@ char *getOperatorName(const char *operatorArg)
       operatorName[len] = '\0';
     }
 
-  /*  return (operatorName); */
+  /*  return operatorName; */
   char * alias = operatorAlias(operatorName);
   return alias;
 }
@@ -247,16 +246,14 @@ char *getOperatorName(const char *operatorArg)
 
 argument_t *file_argument_new(const char *filename)
 {
-  argument_t *argument;
-
-  argument = (argument_t*) Calloc(1, sizeof(argument_t));
+  argument_t *argument = (argument_t*) Calloc(1, sizeof(argument_t));
 
   argument->argc = 1;
   argument->argv = (char **) Calloc(1, sizeof(char *));
   argument->argv[0] = (char *) filename;
   argument->args = (char *) filename;
 
-  return (argument);
+  return argument;
 }
 
 
@@ -276,9 +273,7 @@ void file_argument_free(argument_t *argument)
 
 argument_t *argument_new(size_t argc, size_t len)
 {
-  argument_t *argument;
-
-  argument = (argument_t*) Calloc(1, sizeof(argument_t));
+  argument_t *argument = (argument_t*) Calloc(1, sizeof(argument_t));
 
   if ( argc > 0 )
     {
@@ -289,7 +284,7 @@ argument_t *argument_new(size_t argc, size_t len)
   if ( len > 0 )
     argument->args = (char*) Calloc(len, sizeof(char));
 
-  return (argument);
+  return argument;
 }
 
 
@@ -356,7 +351,7 @@ char *getFileArg(char *argument)
         }
     }
 
-  return (fileArg);
+  return fileArg;
 }
 
 
@@ -396,7 +391,7 @@ double parameter2double(const char *string)
     cdoAbort("Float parameter >%s< contains invalid character at position %d!",
 	     string, (int)(endptr-string+1));
 
-  return (fval);
+  return fval;
 }
 
 
@@ -410,7 +405,7 @@ int parameter2int(const char *string)
     cdoAbort("Integer parameter >%s< contains invalid character at position %d!",
 	     string, (int)(endptr-string+1));
 
-  return (ival);
+  return ival;
 }
 
 
@@ -424,7 +419,7 @@ int parameter2intlist(const char *string)
     cdoAbort("Integer parameter >%s< contains invalid character at position %d!",
 	     string, (int)(endptr-string+1));
 
-  return (ival);
+  return ival;
 }
 
 
@@ -435,11 +430,11 @@ static int season_start = START_DEC;
 
 int get_season_start(void)
 {
-  static int lgetenv = TRUE;
+  static bool lgetenv = true;
 
   if ( lgetenv )
     {
-      lgetenv = FALSE;
+      lgetenv = false;
   
       char *envstr = getenv("CDO_SEASON_START");
       if ( envstr )
@@ -521,7 +516,7 @@ int userFileOverwrite(const char *restrict filename)
 {
   int status = 0;
 
-  if ( stdin_is_tty && stderr_is_tty )
+  if ( !cdoSilentMode && stdin_is_tty && stderr_is_tty )
     {
       fprintf(stderr, "File %s already exists, overwrite? (yes/no): ", filename);
       char line[1024];
@@ -546,13 +541,13 @@ int userFileOverwrite(const char *restrict filename)
 }
 
 
-int ps_lhead = FALSE;
+bool ps_lhead = false;
 int ps_nch   = 0;
 int ps_cval  = -1;
 
 void progressInit(void)
 {
-  ps_lhead = FALSE;
+  ps_lhead = false;
   ps_nch   = 0;
   ps_cval  = -1;
 }
@@ -578,7 +573,7 @@ void progressStatus(double offset, double refval, double curval)
     {
       ps_nch = fprintf(stdout, "%s: %3d%%", processInqPrompt(), 0);
       fflush(stdout);
-      ps_lhead = TRUE;
+      ps_lhead = true;
     }
 
   if ( ival != ps_cval )
@@ -590,7 +585,7 @@ void progressStatus(double offset, double refval, double curval)
 
   if ( ps_cval == 100 && ps_lhead )
     {
-      ps_lhead = FALSE;
+      ps_lhead = false;
       while ( ps_nch-- ) fprintf(stdout, "\b \b");
       fflush(stdout);
     }
@@ -615,7 +610,7 @@ int datatype2str(int datatype, char *datatypestr)
   else if ( datatype == DATATYPE_UINT32 ) strcpy(datatypestr, "U32");
   else                                  { strcpy(datatypestr, "-1"); status = -1;}
 
-  return (status);
+  return status;
 }
 
 
@@ -646,7 +641,7 @@ int str2datatype(const char *datatypestr)
       else if ( strncmp(datatypestr, "double", len) == 0 ) datatype = DATATYPE_FLT64;
     }
 
-  return (datatype);
+  return datatype;
 }
 
 
@@ -677,15 +672,15 @@ const char *filetypeext(int filetype)
   switch ( filetype )
     {
     case FILETYPE_GRB:
-    case FILETYPE_GRB2: return (".grb");   break;
+    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 ("");
+    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 "";
     }
 }
 
@@ -736,8 +731,8 @@ void cdoGenFileSuffix(char *filesuffix, size_t maxlen, int filetype, int vlistID
         }
       else
         {
-          int lready = FALSE;
-          int lcompsz = FALSE;
+          bool lready = false;
+          bool lcompsz = false;
           
           if ( filetype == cdoDefaultFileType && cdoDefaultDataType == -1 && cdoDefaultByteorder == -1 )
             {
@@ -753,20 +748,20 @@ void cdoGenFileSuffix(char *filesuffix, size_t maxlen, int filetype, int vlistID
                       switch (firstchar)
                         {
                         case 'g':
-                          if ( cdoDefaultFileType == FILETYPE_GRB || cdoDefaultFileType == FILETYPE_GRB2 ) lready = TRUE;
+                          if ( cdoDefaultFileType == FILETYPE_GRB || cdoDefaultFileType == FILETYPE_GRB2 ) lready = true;
                           break;
                         case 'n':
                           if ( cdoDefaultFileType == FILETYPE_NC || cdoDefaultFileType == FILETYPE_NC2 ||
-                               cdoDefaultFileType == FILETYPE_NC4 || cdoDefaultFileType == FILETYPE_NC4C ) lready = TRUE;
+                               cdoDefaultFileType == FILETYPE_NC4 || cdoDefaultFileType == FILETYPE_NC4C ) lready = true;
                           break;
                         case 's':
-                          if ( cdoDefaultFileType == FILETYPE_SRV ) lready = TRUE;
+                          if ( cdoDefaultFileType == FILETYPE_SRV ) lready = true;
                           break;
                         case 'e':
-                          if ( cdoDefaultFileType == FILETYPE_EXT ) lready = TRUE;
+                          if ( cdoDefaultFileType == FILETYPE_EXT ) lready = true;
                           break;
                         case 'i':
-                          if ( cdoDefaultFileType == FILETYPE_IEG ) lready = TRUE;
+                          if ( cdoDefaultFileType == FILETYPE_IEG ) lready = true;
                           break;
                         }
                     }
@@ -787,10 +782,10 @@ void cdoGenFileSuffix(char *filesuffix, size_t maxlen, int filetype, int vlistID
           if ( !lready )
             {
               strncat(filesuffix, streamFilesuffix(cdoDefaultFileType), maxlen-1);
-              if ( cdoDefaultFileType == FILETYPE_GRB && vlistIsSzipped(vlistID) ) lcompsz = TRUE;
+              if ( cdoDefaultFileType == FILETYPE_GRB && vlistIsSzipped(vlistID) ) lcompsz = true;
             }
 
-          if ( cdoDefaultFileType == FILETYPE_GRB && cdoCompType == COMPRESS_SZIP ) lcompsz = TRUE;
+          if ( cdoDefaultFileType == FILETYPE_GRB && cdoCompType == COMPRESS_SZIP ) lcompsz = true;
           if ( lcompsz ) strncat(filesuffix, ".sz", maxlen-1);
         }
     }
@@ -806,6 +801,50 @@ int cdoFiletype(void)
         cdoPrint("Set default filetype to GRIB");
     }
 
-  return (cdoDefaultFileType);
+  return cdoDefaultFileType;
 }
 
+
+void cdoSetNAN(double missval, size_t gridsize, double *array)
+{
+  if ( DBL_IS_NAN(missval) )
+    {
+      double newmissval = -9e33;
+      for ( size_t i = 0; i < gridsize; ++i )
+        if ( DBL_IS_EQUAL(array[i], missval) )
+          array[i] = newmissval;
+    }
+}
+
+
+void minmaxval(long nvals, double *array, int *imiss, double *minval, double *maxval)
+{
+  long i;
+  double xmin =  DBL_MAX;
+  double xmax = -DBL_MAX;
+
+  if ( imiss )
+    {
+      for ( i = 0; i < nvals; ++i )
+	{
+	  if ( ! imiss[i] )
+	    {
+	      if      ( array[i] > xmax ) xmax = array[i];
+	      else if ( array[i] < xmin ) xmin = array[i];
+	    }
+	}
+    }
+  else
+    {
+      xmin = array[0];
+      xmax = array[0];
+      for ( i = 1; i < nvals; ++i )
+	{
+	  if      ( array[i] > xmax ) xmax = array[i];
+	  else if ( array[i] < xmin ) xmin = array[i];
+	}
+    }
+
+  *minval = xmin;
+  *maxval = xmax;
+}
diff --git a/src/util.h b/src/util.h
index e3cbddc..3a9ff91 100644
--- a/src/util.h
+++ b/src/util.h
@@ -154,6 +154,8 @@ void    cdiOpenError(int cdiErrno, const char *fmt, const char *path);
 void    cdoAbort(const char *fmt, ...);
 void    cdoWarning(const char *fmt, ...);
 void    cdoPrint(const char *fmt, ...);
+void    cdoPrintBlue(const char *fmt, ...);
+void    cdoPrintRed(const char *fmt, ...);
 
 int  timer_new(const char *text);
 void timer_report(void);
@@ -183,6 +185,8 @@ const char *cdoOperatorEnter(int operID);
 
 int     cdoFiletype(void);
 
+void cdoSetNAN(double missval, size_t gridsize, double *array);
+
 void    cdoInqHistory(int fileID);
 void    cdoDefHistory(int fileID, char *histstring);
 void cdo_def_tracking_id(int vlistID, const char *uuid_attribute);
@@ -195,6 +199,8 @@ int     vlistInqNWPV(int vlistID, int varID);
 int     vlistIsSzipped(int vlistID);
 int     vlist_check_gridsize(int vlistID);
 int     vlist_get_psvarid(int vlistID, int zaxisID);
+double *vlist_read_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlev, int *rnhlevf, int *rnhlevh);
+void vlist_change_hybrid_zaxis(int vlistID1, int vlistID2, int zaxisID1, int zaxisID2);
 
 void cdoGenFileSuffix(char *filesuffix, size_t maxlen, int filetype, int vlistID, const char *refname);
 
diff --git a/src/zaxis.c b/src/zaxis.c
index 8478317..644d186 100644
--- a/src/zaxis.c
+++ b/src/zaxis.c
@@ -93,7 +93,7 @@ static int getoptname(char *optname, const char *optstring, int nopt)
   else
     nerr = 1;
 
-  return (nerr);
+  return nerr;
 }
 
 
@@ -135,7 +135,7 @@ int zaxisDefine(zaxis_t zaxis)
 	Warning("vct undefined!");	    
     }
 
-  return (zaxisID);
+  return zaxisID;
 }
 
 
@@ -145,7 +145,7 @@ static char *skipSeparator(char *pline)
   if ( *pline == '=' || *pline == ':' ) pline++;
   while ( isspace((int) *pline) ) pline++;
 
-  return (pline);
+  return pline;
 }
 
 
@@ -153,7 +153,6 @@ int zaxisFromFile(FILE *gfp, const char *dname)
 {
   char line[MAX_LINE_LEN], *pline;
   int zaxisID;
-  int lerror;
   size_t i, len;
   zaxis_t zaxis;
 
@@ -165,11 +164,11 @@ int zaxisFromFile(FILE *gfp, const char *dname)
       if ( line[0] == '\0' ) continue;
       len = strlen(line);
 
-      lerror = FALSE;
+      bool lerror = false;
       for ( i = 0; i < len; ++i )
 	if ( !(line[i] == 9 || (line[i] > 31 && line[i] < 127)) )
 	  {
-	    lerror = TRUE;
+	    lerror = true;
 	    line[i] = '#';
 	  }
       if ( lerror ) cdoAbort("Zaxis description file >%s< contains illegal characters (line: %s)!", dname, line);
@@ -370,7 +369,7 @@ int zaxisFromFile(FILE *gfp, const char *dname)
 
   zaxisID = zaxisDefine(zaxis);
 
-  return (zaxisID);
+  return zaxisID;
 }
 
 
@@ -393,7 +392,7 @@ int zaxisFromName(const char *zaxisname)
 
   if ( zaxis.type != -1 ) zaxisID = zaxisDefine(zaxis);
 
-  return (zaxisID);
+  return zaxisID;
 }
 
 
@@ -417,7 +416,7 @@ int cdoDefineZaxis(const char *zaxisfile)
 
   if ( zaxisID == -1 ) cdoAbort("Invalid zaxis description file %s!", zaxisfile);
 
-  return (zaxisID);
+  return zaxisID;
 }
 
 
@@ -448,7 +447,7 @@ int ztype2ltype(int zaxistype)
   else if ( zaxistype == ZAXIS_ISENTROPIC        )  ltype = 113;
   else if ( zaxistype == ZAXIS_DEPTH_BELOW_SEA   )  ltype = 160;
 
-  return (ltype);
+  return ltype;
 }
 
 
@@ -463,5 +462,5 @@ int zaxis2ltype(int zaxisID)
 
   if ( ltype <= 0 ) ltype = ztype2ltype(zaxistype);
 
-  return (ltype);
+  return ltype;
 }
diff --git a/test/Afterburner.test.in b/test/Afterburner.test.in
index bb22d5a..250a9a7 100644
--- a/test/Afterburner.test.in
+++ b/test/Afterburner.test.in
@@ -11,8 +11,8 @@ test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
 ABSLIMMAX=0.0001
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT=""
 NTEST=1
 ######################################################
diff --git a/test/Arith.test.in b/test/Arith.test.in
index d894f31..67c4598 100644
--- a/test/Arith.test.in
+++ b/test/Arith.test.in
@@ -4,70 +4,64 @@ echo 1..4 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 STATS="add sub mul div"
 #
-IFILE=$DATAPATH/pl_data
 NTEST=1
 #
 for STAT in $STATS; do
   RSTAT=0
 
-  OFILE=stat${STAT}_res
+  RFILE=$DATAPATH/arith${STAT}_ref
 
-  for VAR in -777 -1 0 1 777; do
-    VAL=1
-    CFILE=constval
-    $CDO -f srv -b 64 const,$VAL,$IFILE $CFILE
+  CDOTEST="$STAT"
+  echo "Running test: $NTEST - $CDOTEST"
 
-# stat var const
+# stat vars mask
 
-    CDOTEST="$STAT"
-    CDOCOMMAND="$CDO $FORMAT ${STAT} $IFILE $CFILE $OFILE"
+  IFILE1=$DATAPATH/arith1.srv
+  IFILE2=$DATAPATH/arithmask.srv
+  OFILE=arith${STAT}_res
 
-    echo "Running test: $NTEST - $CDOTEST"
-    echo "$CDOCOMMAND"
+  CDOCOMMAND="$CDO $FORMAT ${STAT} $IFILE1 $IFILE2 $OFILE"
+  echo $CDOCOMMAND
 
-    $CDOCOMMAND
-    test $? -eq 0 || let RSTAT+=1
+  $CDOCOMMAND
+  test $? -eq 0 || let RSTAT+=1
 
-# stat,const var
+  $CDO diff $OFILE $RFILE > $CDOOUT 2> $CDOERR
+  test $? -eq 0 || let RSTAT+=1
+  test -s $CDOOUT && let RSTAT+=1
+  cat $CDOOUT $CDOERR
 
-    OFILE2=stat${STAT}c_res
-    CDOCOMMAND="$CDO $FORMAT ${STAT}c,$VAL $IFILE $OFILE2"
+  rm -f $OFILE
 
-    $CDOCOMMAND
-    test $? -eq 0 || let RSTAT+=1
+# expr,instr var
 
-    $CDO diff $OFILE $OFILE2 > $CDOOUT 2> $CDOERR
-    test $? -eq 0 || let RSTAT+=1
-    test -s $CDOOUT && let RSTAT+=1
-    cat $CDOOUT $CDOERR
+  OP=""
+  if [ "$STAT" = add ] ; then OP='+' ; fi
+  if [ "$STAT" = sub ] ; then OP='-' ; fi
+  if [ "$STAT" = mul ] ; then OP='*' ; fi
+  if [ "$STAT" = div ] ; then OP='/' ; fi
 
-# expr,instr var
+  IFILE=$DATAPATH/expr1.srv
+  OFILE=expr${STAT}_res
+
+  INSTR="var215=var215${OP}var3;var216=var216${OP}var3;"
+  echo $INSTR
+  CDOCOMMAND="$CDO $FORMAT expr,$INSTR $IFILE $OFILE"
+
+  $CDOCOMMAND
+  test $? -eq 0 || let RSTAT+=1
+
+  $CDO diff $OFILE $RFILE > $CDOOUT 2> $CDOERR
+  test $? -eq 0 || let RSTAT+=1
+  test -s $CDOOUT && let RSTAT+=1
+  cat $CDOOUT $CDOERR
 
-    OP=""
-    if [ "$STAT" = add ] ; then OP='+' ; fi
-    if [ "$STAT" = sub ] ; then OP='-' ; fi
-    if [ "$STAT" = mul ] ; then OP='*' ; fi
-    if [ "$STAT" = div ] ; then OP='/' ; fi
-    OFILE3=expr${STAT}_res
-    INSTR="var130=var130${OP}${VAL};var152=var152${OP}${VAL};var129=var129${OP}${VAL};"
-    echo $INSTR
-    CDOCOMMAND="$CDO $FORMAT expr,$INSTR $IFILE $OFILE3"
-
-    $CDOCOMMAND
-    test $? -eq 0 || let RSTAT+=1
-
-    $CDO diff $OFILE $OFILE3 > $CDOOUT 2> $CDOERR
-    test $? -eq 0 || let RSTAT+=1
-    test -s $CDOOUT && let RSTAT+=1
-    cat $CDOOUT $CDOERR
-
-    rm -f $OFILE $OFILE2 $OFILE3 $CFILE
-  done
+  rm -f $OFILE
 
   test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
   test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
diff --git a/test/Arith.test.in b/test/Arithc.test.in
similarity index 98%
copy from test/Arith.test.in
copy to test/Arithc.test.in
index d894f31..3b2eb88 100644
--- a/test/Arith.test.in
+++ b/test/Arithc.test.in
@@ -4,8 +4,8 @@ echo 1..4 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 STATS="add sub mul div"
 #
diff --git a/test/Cat.test.in b/test/Cat.test.in
index 8940944..a931582 100644
--- a/test/Cat.test.in
+++ b/test/Cat.test.in
@@ -4,8 +4,8 @@ echo 1..1 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 RSTAT=0
 #
diff --git a/test/Collgrid.test.in b/test/Collgrid.test.in
index 06c6470..42f9797 100644
--- a/test/Collgrid.test.in
+++ b/test/Collgrid.test.in
@@ -4,8 +4,8 @@ echo 1..9 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 #
 GRIDTYPES="regular generic curvilinear"
 DISTS="4,3 12,1 1,6"
diff --git a/test/Copy_netcdf.test.in b/test/Copy_netcdf.test.in
index 5bdc4be..cc4efd5 100644
--- a/test/Copy_netcdf.test.in
+++ b/test/Copy_netcdf.test.in
@@ -4,8 +4,8 @@ echo 1..5 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 #
 FILES="datar.nc datag.nc datac.nc datau.nc testfile01c.nc"
 #
diff --git a/test/Detrend.test.in b/test/Detrend.test.in
index b4a0fb0..1bf8c03 100644
--- a/test/Detrend.test.in
+++ b/test/Detrend.test.in
@@ -4,8 +4,8 @@ echo 1..2 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 #
 IFILE=$DATAPATH/detrend_data
 NTEST=1
diff --git a/test/Enspctl.test.in b/test/Enspctl.test.in
index ee6dd33..62e8abe 100644
--- a/test/Enspctl.test.in
+++ b/test/Enspctl.test.in
@@ -4,14 +4,14 @@ echo 1..1 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 PCTLS="1 20 25 33 50 66 75 80 99 100"
 #
 IFILE=$DATAPATH/ts_mm_5years
 export CDO_FILE_SUFFIX=NULL
-$CDO splityear $IFILE ts_year
-IFILE="ts_year????"
+$CDO splityear $IFILE ${$}ts_year
+IFILES="${$}ts_year????"
 #
 NTEST=1
 RSTAT=0
@@ -22,7 +22,7 @@ for PCTL in $PCTLS; do
   OFILE=enspctl${STAT}_res
 
   CDOTEST="enspctl"
-  CDOCOMMAND="$CDO enspctl,${PCTL} $IFILE $OFILE"
+  CDOCOMMAND="$CDO enspctl,${PCTL} $IFILES $OFILE"
 
   echo "$CDOCOMMAND"
 
@@ -42,6 +42,6 @@ test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
 test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
 #
 rm -f $CDOOUT $CDOERR
-rm -f $IFILE
+rm -f $IFILES
 #
 exit 0
diff --git a/test/Ensstat.test.in b/test/Ensstat.test.in
index 32149f5..1aadb19 100644
--- a/test/Ensstat.test.in
+++ b/test/Ensstat.test.in
@@ -4,14 +4,14 @@ echo 1..9 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 STATS="min max sum avg mean std std1 var var1"
 #
 IFILE=$DATAPATH/ts_mm_5years
 export CDO_FILE_SUFFIX=NULL
-$CDO splityear $IFILE ts_year
-IFILE="ts_year????"
+$CDO splityear $IFILE ${$}ts_year
+IFILES="${$}ts_year????"
 #
 NTEST=1
 #
@@ -21,7 +21,7 @@ for STAT in $STATS; do
   OFILE=ens${STAT}_res
 
   CDOTEST="ens$STAT"
-  CDOCOMMAND="$CDO ens${STAT} $IFILE $OFILE"
+  CDOCOMMAND="$CDO ens${STAT} $IFILES $OFILE"
 
   echo "Running test: $NTEST"
   echo "$CDOCOMMAND"
@@ -42,6 +42,6 @@ for STAT in $STATS; do
 done
 #
 rm -f $CDOOUT $CDOERR
-rm -f $IFILE
+rm -f $IFILES
 #
 exit 0
diff --git a/test/Expr.test.in b/test/Expr.test.in
index db9accd..ee2c883 100644
--- a/test/Expr.test.in
+++ b/test/Expr.test.in
@@ -4,8 +4,8 @@ echo 1..2 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 #
 IFILE=$DATAPATH/pl_data
diff --git a/test/File.test.in b/test/File.test.in
index 3df3321..8d0d00d 100644
--- a/test/File.test.in
+++ b/test/File.test.in
@@ -4,12 +4,36 @@ echo 1..16 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMATS="srv ext ieg grb grb2 nc nc2 nc4"
 #
 NTEST=1
 #
+function fileformat()
+{
+  FILEFORMAT=undefined
+  ENABLE_TEST=yes
+
+  if [ "${FORMAT}" = srv  ] ; then  FILEFORMAT=SERVICE;  fi
+  if [ "${FORMAT}" = ext  ] ; then  FILEFORMAT=EXTRA;    fi
+  if [ "${FORMAT}" = ieg  ] ; then  FILEFORMAT=IEG;      fi
+  if [ "${FORMAT}" = grb  ] ; then  FILEFORMAT=GRIB;     fi
+  if [ "${FORMAT}" = grb2 ] ; then  FILEFORMAT=GRIB_API; fi
+  if [ "${FORMAT}" = nc   ] ; then  FILEFORMAT=netCDF;   fi
+  if [ "${FORMAT}" = nc2  ] ; then  FILEFORMAT=netCDF2;  fi
+  if [ "${FORMAT}" = nc4  ] ; then  FILEFORMAT=netCDF4;  fi
+
+  if [ "@ENABLE_SERVICE@" = no -a "${FORMAT}" = srv  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_EXTRA@" = no   -a "${FORMAT}" = ext  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_IEG@" = no     -a "${FORMAT}" = ieg  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_GRIB@" = no    -a "${FORMAT}" = grb  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_GRIBAPI@" = no -a "${FORMAT}" = grb2 ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_NETCDF@" = no  -a "${FORMAT}" = nc   ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_NETCDF@" = no  -a "${FORMAT}" = nc2  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_NC4@" = no     -a "${FORMAT}" = nc4  ] ; then  ENABLE_TEST=no; fi
+}
+#
 for OPERATOR in write copy; do
   for FORMAT in $FORMATS; do
     RSTAT=0
@@ -17,42 +41,12 @@ for OPERATOR in write copy; do
     CDOTEST="$OPERATOR $FORMAT"
     echo "Running test: $NTEST"
 
-    ENABLED_TEST=yes
+    FILEFORMAT=undefined
+    ENABLE_TEST=yes
 
-    if [ "@ENABLE_SERVICE@" = no -a "${FORMAT}" = srv ] ; then
-      FILEFORMAT=SERVICE
-      ENABLED_TEST=no
-    fi
-    if [ "@ENABLE_EXTRA@" = no -a "${FORMAT}" = ext ] ; then
-      FILEFORMAT=EXTRA
-      ENABLED_TEST=no
-    fi
-    if [ "@ENABLE_IEG@" = no -a "${FORMAT}" = ieg ] ; then
-      FILEFORMAT=IEG
-      ENABLED_TEST=no
-    fi
-    if [ "@ENABLE_GRIB@" = no -a "${FORMAT}" = grb ] ; then
-      FILEFORMAT=GRIB
-      ENABLED_TEST=no
-    fi
-    if [ "@ENABLE_GRIBAPI@" = no -a "${FORMAT}" = grb2 ] ; then
-      FILEFORMAT=GRIB_API
-      ENABLED_TEST=no
-    fi
-    if [ "@ENABLE_NETCDF@" = no -a "${FORMAT}" = nc ] ; then
-      FILEFORMAT=netCDF
-      ENABLED_TEST=no
-    fi
-    if [ "@ENABLE_NETCDF@" = no -a "${FORMAT}" = nc2 ] ; then
-      FILEFORMAT=netCDF2
-      ENABLED_TEST=no
-    fi
-    if [ "@ENABLE_NC4@" = no -a "${FORMAT}" = nc4 ] ; then
-      FILEFORMAT=netCDF4
-      ENABLED_TEST=no
-    fi
+    fileformat
 
-    if [ "${ENABLED_TEST}" = yes ] ; then
+    if [ "${ENABLE_TEST}" = yes ] ; then
       for DATATYPE in F32 F64; do
         FILE=file_${DATATYPE}_${FORMAT}
         RFILE=$DATAPATH/file_F32_srv_ref
diff --git a/test/Fldpctl.test.in b/test/Fldpctl.test.in
index 33a0dec..8344c6f 100644
--- a/test/Fldpctl.test.in
+++ b/test/Fldpctl.test.in
@@ -4,8 +4,8 @@ echo 1..1 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 #
 PCTLS="1 20 25 33 50 66 75 80 99 100"
diff --git a/test/Fldstat.test.in b/test/Fldstat.test.in
index b19a46d..5bbccab 100644
--- a/test/Fldstat.test.in
+++ b/test/Fldstat.test.in
@@ -4,8 +4,8 @@ echo 1..9 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 #
 STATS="min max sum avg mean std std1 var var1"
diff --git a/test/Genweights.test.in b/test/Genweights.test.in
index 80e71a8..bf88738 100644
--- a/test/Genweights.test.in
+++ b/test/Genweights.test.in
@@ -11,8 +11,8 @@ test -n "$DATAPATH" || DATAPATH=./data
 ABSLIMMAX=0.001
 ABSLIMDIS=0.2
 ABSLIMYCON=0.25
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 GRIDS="n16 n32"
 #
@@ -32,35 +32,39 @@ for GRIDTYPE in "regular" "curvilinear" "unstructured"; do
       if [ $RMOD = dis ];  then ABSLIM=$ABSLIMDIS; fi
       if [ $RMOD = ycon ]; then ABSLIM=$ABSLIMYCON; fi
       RSTAT=0
-      OFILE=${GRID}_${RMOD}
-      RFILE=$DATAPATH/${OFILE}_ref
+      OFILE=${GRID}_${RMOD}_$$
+      RFILE=$DATAPATH/${GRID}_${RMOD}_ref
 
       CDOTEST="gen${RMOD} $GRID $GRIDTYPE"
       CDOCOMMAND="$CDO $FORMAT gen${RMOD},$GRID $SETGRID $IFILE remapweights"
 
-      if [ "@ENABLE_NETCDF@" = yes ] ; then
-        echo "Running test: $NTEST"
-        echo "$CDOCOMMAND"
+      if [ "@ENABLE_THREADS@" = no -a "$GRIDTYPE" != "regular" ]; then
+        test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP POSIX threads not enabled"
+      else
+        if [ "@ENABLE_NETCDF@" = yes ] ; then
+          echo "Running test: $NTEST"
+          echo "$CDOCOMMAND"
 
-        $CDOCOMMAND
-        test $? -eq 0 || let RSTAT+=1
+          $CDOCOMMAND
+          test $? -eq 0 || let RSTAT+=1
 
-        $CDO $FORMAT remap,$GRID,remapweights $SETGRID $IFILE ${OFILE}
-        test $? -eq 0 || let RSTAT+=1
+          $CDO $FORMAT remap,$GRID,remapweights $SETGRID $IFILE ${OFILE}
+          test $? -eq 0 || let RSTAT+=1
 
-        $CDO diff,$ABSLIM $OFILE $RFILE > $CDOOUT 2> $CDOERR
-        test $? -eq 0 || let RSTAT+=1
-        test -s $CDOOUT && let RSTAT+=1
-        cat $CDOOUT $CDOERR
+          $CDO diff,$ABSLIM $OFILE $RFILE > $CDOOUT 2> $CDOERR
+          test $? -eq 0 || let RSTAT+=1
+          test -s $CDOOUT && let RSTAT+=1
+          cat $CDOOUT $CDOERR
 
-        test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
-        if [ $RMOD = dis ]; then
-          test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST # TODO check depends on optimization"
+          test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
+          if [ $RMOD = dis ]; then
+            test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST # TODO check depends on optimization"
+          else
+            test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+          fi
         else
-          test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+          test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP netCDF not enabled"
         fi
-      else
-        test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP netCDF not enabled"
       fi
 
       let NTEST+=1
diff --git a/test/Gradsdes.test.in b/test/Gradsdes.test.in
index 0822cab..225c466 100644
--- a/test/Gradsdes.test.in
+++ b/test/Gradsdes.test.in
@@ -4,8 +4,8 @@ echo 1..1 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 #
 IFILE=$DATAPATH/pl_data.grb
 OFILE=pl_data.grb
diff --git a/test/Gridarea.test.in b/test/Gridarea.test.in
index 5aab9b8..45f2e00 100644
--- a/test/Gridarea.test.in
+++ b/test/Gridarea.test.in
@@ -4,8 +4,8 @@ echo 1..7 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 REFVAL="12.5663706"
 GRIDS="global_5 global_2 global_1 global_.5 n32 n80 n160"
 RSTAT=0;
@@ -18,15 +18,19 @@ for GRID in $GRIDS; do
   CDOTEST="gridarea $GRID"
   CDOCOMMAND="$CDO outputf,%10.7f -fldsum -gridarea -random,$GRID"
 
-  echo "Running test: $NTEST"
-  echo "$CDOCOMMAND"
+  if [ "@ENABLE_THREADS@" = yes ] ; then
+    echo "Running test: $NTEST"
+    echo "$CDOCOMMAND"
 
-  GLOBAREA=`$CDOCOMMAND`
-  echo "gridarea $GRID: >$GLOBAREA< >$REFVAL<"
-  if [ "$GLOBAREA" != "$REFVAL" ]; then RSTAT=`expr $RSTAT + 1`; fi
+    GLOBAREA=`$CDOCOMMAND`
+    echo "gridarea $GRID: >$GLOBAREA< >$REFVAL<"
+    if [ "$GLOBAREA" != "$REFVAL" ]; then RSTAT=`expr $RSTAT + 1`; fi
 
-  test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
-  test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+    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 POSIX threads not enabled"
+  fi
 
   let NTEST+=1
 done
diff --git a/test/Makefile.am b/test/Makefile.am
index 50e2f7c..564e053 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -11,10 +11,10 @@ TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
                   $(top_srcdir)/config/tap-driver.sh
 
 # tests which should pass
-TESTS = threads.test wildcard.test File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test Detrend.test \
-        Genweights.test Remap.test Select.test Spectral.test Ymonstat.test Timstat.test Ensstat.test \
-        Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arith.test Expr.test \
-        Gradsdes.test Collgrid.test
+TESTS = threads.test tsformat.test wildcard.test File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test  \
+        Detrend.test Genweights.test Remap.test Select.test Spectral.test Ymonstat.test Timstat.test Ensstat.test \
+        Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arithc.test Arith.test Expr.test \
+        Gradsdes.test Collgrid.test MapReduce.test Ninfo.test
 
 # tests which should fail
 XFAIL_TESTS = 
diff --git a/test/Makefile.in b/test/Makefile.in
index 3de2043..dafd17f 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -90,9 +90,11 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(srcdir)/Fldstat.test.in $(srcdir)/Fldpctl.test.in \
 	$(srcdir)/Ensstat.test.in $(srcdir)/Enspctl.test.in \
 	$(srcdir)/Afterburner.test.in $(srcdir)/Detrend.test.in \
-	$(srcdir)/Arith.test.in $(srcdir)/Expr.test.in \
-	$(srcdir)/Gradsdes.test.in $(srcdir)/Collgrid.test.in \
-	$(srcdir)/threads.test.in $(srcdir)/wildcard.test.in README
+	$(srcdir)/Arithc.test.in $(srcdir)/Arith.test.in \
+	$(srcdir)/Expr.test.in $(srcdir)/Gradsdes.test.in \
+	$(srcdir)/Collgrid.test.in $(srcdir)/threads.test.in \
+	$(srcdir)/tsformat.test.in $(srcdir)/wildcard.test.in \
+	$(srcdir)/MapReduce.test.in $(srcdir)/Ninfo.test.in README
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
@@ -107,9 +109,9 @@ CONFIG_CLEAN_FILES = File.test Read_grib.test Read_netcdf.test \
 	Copy_netcdf.test Cat.test Gridarea.test Genweights.test \
 	Remap.test Select.test Spectral.test Timstat.test Vertint.test \
 	Ymonstat.test Fldstat.test Fldpctl.test Ensstat.test \
-	Enspctl.test Afterburner.test Detrend.test Arith.test \
-	Expr.test Gradsdes.test Collgrid.test threads.test \
-	wildcard.test
+	Enspctl.test Afterburner.test Detrend.test Arithc.test \
+	Arith.test Expr.test Gradsdes.test Collgrid.test threads.test \
+	tsformat.test wildcard.test MapReduce.test Ninfo.test
 CONFIG_CLEAN_VPATH_FILES =
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
@@ -450,8 +452,6 @@ UDUNITS_LDFLAGS = @UDUNITS_LDFLAGS@
 USER_NAME = @USER_NAME@
 VERSION = @VERSION@
 XML2_LIBS = @XML2_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -520,10 +520,10 @@ TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
 
 
 # tests which should pass
-TESTS = threads.test wildcard.test File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test Detrend.test \
-        Genweights.test Remap.test Select.test Spectral.test Ymonstat.test Timstat.test Ensstat.test \
-        Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arith.test Expr.test \
-        Gradsdes.test Collgrid.test
+TESTS = threads.test tsformat.test wildcard.test File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test  \
+        Detrend.test Genweights.test Remap.test Select.test Spectral.test Ymonstat.test Timstat.test Ensstat.test \
+        Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arithc.test Arith.test Expr.test \
+        Gradsdes.test Collgrid.test MapReduce.test Ninfo.test
 
 
 #        $(top_srcdir)/test/test_Remap.sh \
@@ -610,6 +610,8 @@ Afterburner.test: $(top_builddir)/config.status $(srcdir)/Afterburner.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 Detrend.test: $(top_builddir)/config.status $(srcdir)/Detrend.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+Arithc.test: $(top_builddir)/config.status $(srcdir)/Arithc.test.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 Arith.test: $(top_builddir)/config.status $(srcdir)/Arith.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 Expr.test: $(top_builddir)/config.status $(srcdir)/Expr.test.in
@@ -620,8 +622,14 @@ Collgrid.test: $(top_builddir)/config.status $(srcdir)/Collgrid.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 threads.test: $(top_builddir)/config.status $(srcdir)/threads.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+tsformat.test: $(top_builddir)/config.status $(srcdir)/tsformat.test.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 wildcard.test: $(top_builddir)/config.status $(srcdir)/wildcard.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+MapReduce.test: $(top_builddir)/config.status $(srcdir)/MapReduce.test.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+Ninfo.test: $(top_builddir)/config.status $(srcdir)/Ninfo.test.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 
 mostlyclean-libtool:
 	-rm -f *.lo
diff --git a/test/MapReduce.test.in b/test/MapReduce.test.in
new file mode 100644
index 0000000..22e3669
--- /dev/null
+++ b/test/MapReduce.test.in
@@ -0,0 +1,50 @@
+#! @SHELL@
+echo 1..2 # Number of tests to be executed.
+#
+test -n "$CDO"      || CDO=cdo
+test -n "$DATAPATH" || DATAPATH=./data
+#
+NTEST=1
+#
+for OPERATOR in reducegrid; do
+  for grid  in r18x9 icon_cell; do
+    RSTAT=0
+
+    REFGRID="${DATAPATH}/${grid}_grid"
+    REF="$DATAPATH/griddes.${grid}"
+
+    CDOTEST="$OPERATOR on grid ${grid}"
+
+    if [ "@ENABLE_NETCDF@" = yes ] ; then
+
+      $CDO -f nc -temp,$REFGRID data_${grid}.nc
+      $CDO -f nc -gtc,273.15 -temp,$REFGRID mask_${grid}.nc
+
+      echo "Running test: $NTEST"
+      CDOCOMMAND="$CDO -f nc reducegrid,mask_${grid}.nc data_${grid}.nc reduced_${grid}.nc"
+      echo "$CDOCOMMAND"
+
+      $CDOCOMMAND
+      test $? -eq 0 || let RSTAT+=1
+
+      $CDO griddes reduced_${grid}.nc > griddes.${grid}
+      cmp griddes.${grid} $REF
+      test $? -eq 0 || let RSTAT+=1
+
+      rm reduced_${grid}.nc
+      rm griddes.${grid}
+
+      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
+
+    rm data_${grid}.nc
+    rm mask_${grid}.nc
+
+    let NTEST+=1
+  done
+done
+#
+exit 0
diff --git a/test/Ninfo.test.in b/test/Ninfo.test.in
new file mode 100644
index 0000000..bf74c0a
--- /dev/null
+++ b/test/Ninfo.test.in
@@ -0,0 +1,61 @@
+#! @SHELL@
+echo 1..9 # Number of tests to be executed.
+#
+test -n "$CDO"      || CDO=cdo
+#
+NTEST=1
+#
+for grid  in r18x9 ni4 ni96 global_10 t63grid; do
+  RSTAT=0
+
+  OPERATOR=ngridpoints
+  CDOTEST="$OPERATOR on grid ${grid}"
+
+  CDOCOMMAND="$CDO -s -${OPERATOR} -topo,${grid}"
+  echo "$CDOCOMMAND"
+
+  $CDOCOMMAND
+  test $? -eq 0 || let RSTAT+=1
+  case $grid in
+    r18x9)
+      if test 162   -eq $($CDOCOMMAND) ; then  echo "ok $NTEST - $CDOTEST"; else echo "not ok $NTEST - $CDOTEST"; fi
+      ;;
+    ni4)
+      if test 250   -eq $($CDOCOMMAND) ; then  echo "ok $NTEST - $CDOTEST"; else echo "not ok $NTEST - $CDOTEST"; fi
+      ;;
+    ni96)
+      if test 94090 -eq $($CDOCOMMAND) ; then  echo "ok $NTEST - $CDOTEST"; else echo "not ok $NTEST - $CDOTEST"; fi
+      ;;
+    global_10)
+      if test 648   -eq $($CDOCOMMAND) ; then  echo "ok $NTEST - $CDOTEST"; else echo "not ok $NTEST - $CDOTEST"; fi
+      ;;
+    t63grid)
+      if test 18432 -eq $($CDOCOMMAND) ; then  echo "ok $NTEST - $CDOTEST"; else echo "not ok $NTEST - $CDOTEST"; fi
+      ;;
+  esac
+
+  let NTEST+=1
+done
+# some addional test for operator: ngrids
+CDOCOMMAND="$CDO -O -s -ngrids"
+$CDOCOMMAND -topo,global_10
+test $? -eq 0 || let RSTAT+=1
+test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
+test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+let NTEST+=1
+
+if test 1 -eq $($CDOCOMMAND -topo,r1x1) ; then  echo "ok $NTEST - $CDOCOMMAND -topo,r1x1"; else echo "not ok $NTEST - $CDOCOMMAND -topo,r1x1"; fi; let NTEST+=1
+if test 1 -eq $($CDOCOMMAND -topo,global_1) ; then  echo "ok $NTEST - $CDOCOMMAND -topo,global_1"; else echo "not ok $NTEST - $CDOCOMMAND -topo,global_1"; fi; let NTEST+=1
+
+# create temporary data
+if [ "@ENABLE_NETCDF@" = yes ] ; then
+  $CDO -O -f nc -temp,r18x9 temp.small
+  $CDO -O -f nc -temp,global_10 temp.global
+  $CDO -O -f nc -merge temp.small temp.global temp.2grids
+  if test 2 -eq $($CDOCOMMAND temp.2grids) ; then  echo "ok $NTEST - $CDOCOMMAND temp.2grids"; else echo "not ok $NTEST - $CDOCOMMAND temp.2grids"; fi; let NTEST+=1
+  else
+    test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP netCDF not enabled"
+  fi
+
+#
+exit 0
diff --git a/test/Read_grib.test.in b/test/Read_grib.test.in
index 2387e05..5499387 100644
--- a/test/Read_grib.test.in
+++ b/test/Read_grib.test.in
@@ -1,16 +1,16 @@
 #! @SHELL@
-echo 1..4 # Number of tests to be executed.
+echo 1..6 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 #
 NTEST=1
 #
 for OPERATOR in sinfo info; do
-  for FILE in testfile01 testfile02; do
+  for FILE in testfile01 testfile02 testfile03; do
     RSTAT=0
     IFILE=$DATAPATH/grib_${FILE}.grb
     OFILE=grib_${FILE}_${OPERATOR}
diff --git a/test/Read_netcdf.test.in b/test/Read_netcdf.test.in
index 9867367..958344b 100644
--- a/test/Read_netcdf.test.in
+++ b/test/Read_netcdf.test.in
@@ -4,8 +4,8 @@ echo 1..4 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 #
 NTEST=1
 #
diff --git a/test/Remap.test.in b/test/Remap.test.in
index ea20428..0b5e43a 100644
--- a/test/Remap.test.in
+++ b/test/Remap.test.in
@@ -11,8 +11,8 @@ test -n "$DATAPATH" || DATAPATH=./data
 ABSLIMMAX=0.001
 ABSLIMDIS=0.2
 ABSLIMYCON=0.25
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 GRIDS="n16 n32"
 #
@@ -32,28 +32,32 @@ for GRIDTYPE in "regular" "curvilinear" "unstructured"; do
       if [ $RMOD = dis ];  then ABSLIM=$ABSLIMDIS; fi
       if [ $RMOD = ycon ]; then ABSLIM=$ABSLIMYCON; fi
       RSTAT=0
-      OFILE=${GRID}_${RMOD}
-      RFILE=$DATAPATH/${OFILE}_ref
+      OFILE=${GRID}_${RMOD}_$$
+      RFILE=$DATAPATH/${GRID}_${RMOD}_ref
 
       CDOTEST="remap${RMOD} $GRID $GRIDTYPE"
       CDOCOMMAND="$CDO $FORMAT remap${RMOD},$GRID $SETGRID $IFILE ${OFILE}"
 
-      echo "Running test: $NTEST"
-      echo "$CDOCOMMAND"
+      if [ "@ENABLE_THREADS@" = no -a "$GRIDTYPE" != "regular" ]; then
+        test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP POSIX threads not enabled"
+      else
+        echo "Running test: $NTEST"
+        echo "$CDOCOMMAND"
 
-      $CDOCOMMAND
-      test $? -eq 0 || let RSTAT+=1
+        $CDOCOMMAND
+        test $? -eq 0 || let RSTAT+=1
 
-      $CDO diff,$ABSLIM $OFILE $RFILE > $CDOOUT 2> $CDOERR
-      test $? -eq 0 || let RSTAT+=1
-      test -s $CDOOUT && let RSTAT+=1
-      cat $CDOOUT $CDOERR
+        $CDO diff,$ABSLIM $OFILE $RFILE > $CDOOUT 2> $CDOERR
+        test $? -eq 0 || let RSTAT+=1
+        test -s $CDOOUT && let RSTAT+=1
+        cat $CDOOUT $CDOERR
 
-      test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
-      if [ $RMOD = dis ]; then
-        test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST # TODO check depends on optimization"
-      else
-        test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+        test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
+        if [ $RMOD = dis ]; then
+          test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST # TODO check depends on optimization"
+        else
+          test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+        fi
       fi
 
       let NTEST+=1
diff --git a/test/Select.test.in b/test/Select.test.in
index c21abbf..77a73c3 100644
--- a/test/Select.test.in
+++ b/test/Select.test.in
@@ -4,8 +4,8 @@ echo 1..8 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 RSTAT=0;
 #
diff --git a/test/Spectral.test.in b/test/Spectral.test.in
index c7aaea0..90a4352 100644
--- a/test/Spectral.test.in
+++ b/test/Spectral.test.in
@@ -4,8 +4,8 @@ echo 1..4 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT=""
 NTEST=1
 #####################################################
diff --git a/test/Timstat.test.in b/test/Timstat.test.in
index 03c3317..b410cf9 100644
--- a/test/Timstat.test.in
+++ b/test/Timstat.test.in
@@ -4,8 +4,8 @@ echo 1..9 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 STATS="min max sum avg mean std std1 var var1"
 #
 IFILE=$DATAPATH/ts_mm_5years
diff --git a/test/Vertint.test.in b/test/Vertint.test.in
index d03ea63..8e031b3 100644
--- a/test/Vertint.test.in
+++ b/test/Vertint.test.in
@@ -4,8 +4,8 @@ echo 1..1 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 FORMAT="-f srv -b 32"
 RSTAT=0
 #
diff --git a/test/Ymonstat.test.in b/test/Ymonstat.test.in
index 0cafacb..c81f81f 100644
--- a/test/Ymonstat.test.in
+++ b/test/Ymonstat.test.in
@@ -4,8 +4,8 @@ echo 1..9 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 STATS="min max sum avg mean std std1 var var1"
 #
 IFILE=$DATAPATH/ts_mm_5years
diff --git a/test/data/Makefile.am b/test/data/Makefile.am
index 0a32f15..fb636f3 100644
--- a/test/data/Makefile.am
+++ b/test/data/Makefile.am
@@ -1,9 +1,9 @@
 INPUTDATA = ts_mm_5years hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data pl_data.grb detrend_data \
-            grib_testfile01.grb grib_testfile02.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
-            datar.nc datac.nc datau.nc datag.nc
+            grib_testfile01.grb grib_testfile02.grb grib_testfile03.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
+            datar.nc datac.nc datau.nc datag.nc arith1.srv expr1.srv arithmask.srv
 
 FILE_REF     = file_F32_srv_ref
-GRIB_REF     = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref
+GRIB_REF     = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref grib_testfile03_sinfo_ref grib_testfile03_info_ref
 NETCDF_REF   = netcdf_testfile01_sinfon_ref netcdf_testfile01_infon_ref netcdf_testfile02_sinfon_ref netcdf_testfile02_infon_ref
 YMONSTAT_REF = ymonmin_ref ymonmax_ref ymonsum_ref ymonavg_ref ymonmean_ref ymonstd_ref ymonstd1_ref ymonvar_ref ymonvar1_ref
 TIMSTAT_REF  = timmin_ref timmax_ref timsum_ref timavg_ref timmean_ref timstd_ref timstd1_ref timvar_ref timvar1_ref
@@ -17,7 +17,9 @@ 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
 EXPR_REF     = expr1_ref aexpr1_ref expr2_ref aexpr2_ref
-THREAD_REF   = thread1_ref
+THREAD_REF   = thread1_ref tsformat1_ref
 GRADSDES_REF = pl_data.ctl pl_data.gmp
+ARITH_REF    = arithadd_ref arithsub_ref arithmul_ref arithdiv_ref
+MAPREDUCE    = r18x9_grid icon_cell_grid griddes.r18x9 griddes.icon_cell
 
-EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF)
+EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF) $(ARITH_REF) $(MAPREDUCE)
diff --git a/test/data/Makefile.in b/test/data/Makefile.in
index 5ae555f..e974fb9 100644
--- a/test/data/Makefile.in
+++ b/test/data/Makefile.in
@@ -230,8 +230,6 @@ UDUNITS_LDFLAGS = @UDUNITS_LDFLAGS@
 USER_NAME = @USER_NAME@
 VERSION = @VERSION@
 XML2_LIBS = @XML2_LIBS@
-ZLIB_INCLUDE = @ZLIB_INCLUDE@
-ZLIB_LIBS = @ZLIB_LIBS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -288,11 +286,11 @@ 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 pl_data.grb detrend_data \
-            grib_testfile01.grb grib_testfile02.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
-            datar.nc datac.nc datau.nc datag.nc
+            grib_testfile01.grb grib_testfile02.grb grib_testfile03.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
+            datar.nc datac.nc datau.nc datag.nc arith1.srv expr1.srv arithmask.srv
 
 FILE_REF = file_F32_srv_ref
-GRIB_REF = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref
+GRIB_REF = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref grib_testfile03_sinfo_ref grib_testfile03_info_ref
 NETCDF_REF = netcdf_testfile01_sinfon_ref netcdf_testfile01_infon_ref netcdf_testfile02_sinfon_ref netcdf_testfile02_infon_ref
 YMONSTAT_REF = ymonmin_ref ymonmax_ref ymonsum_ref ymonavg_ref ymonmean_ref ymonstd_ref ymonstd1_ref ymonvar_ref ymonvar1_ref
 TIMSTAT_REF = timmin_ref timmax_ref timsum_ref timavg_ref timmean_ref timstd_ref timstd1_ref timvar_ref timvar1_ref
@@ -307,9 +305,11 @@ 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
 EXPR_REF = expr1_ref aexpr1_ref expr2_ref aexpr2_ref
-THREAD_REF = thread1_ref
+THREAD_REF = thread1_ref tsformat1_ref
 GRADSDES_REF = pl_data.ctl pl_data.gmp
-EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF)
+ARITH_REF = arithadd_ref arithsub_ref arithmul_ref arithdiv_ref
+MAPREDUCE = r18x9_grid icon_cell_grid griddes.r18x9 griddes.icon_cell
+EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF) $(ARITH_REF) $(MAPREDUCE)
 all: all-am
 
 .SUFFIXES:
diff --git a/test/data/arith1.srv b/test/data/arith1.srv
new file mode 100644
index 0000000..67db42e
Binary files /dev/null and b/test/data/arith1.srv differ
diff --git a/test/data/arithadd_ref b/test/data/arithadd_ref
new file mode 100644
index 0000000..53d7363
Binary files /dev/null and b/test/data/arithadd_ref differ
diff --git a/test/data/arithdiv_ref b/test/data/arithdiv_ref
new file mode 100644
index 0000000..8afac80
Binary files /dev/null and b/test/data/arithdiv_ref differ
diff --git a/test/data/arithmask.srv b/test/data/arithmask.srv
new file mode 100644
index 0000000..2b51fca
Binary files /dev/null and b/test/data/arithmask.srv differ
diff --git a/test/data/arithmul_ref b/test/data/arithmul_ref
new file mode 100644
index 0000000..152b2ca
Binary files /dev/null and b/test/data/arithmul_ref differ
diff --git a/test/data/arithsub_ref b/test/data/arithsub_ref
new file mode 100644
index 0000000..8304f4d
Binary files /dev/null and b/test/data/arithsub_ref differ
diff --git a/test/data/expr1.srv b/test/data/expr1.srv
new file mode 100644
index 0000000..a119f67
Binary files /dev/null and b/test/data/expr1.srv differ
diff --git a/test/data/grib_testfile03.grb b/test/data/grib_testfile03.grb
new file mode 100644
index 0000000..a561396
Binary files /dev/null and b/test/data/grib_testfile03.grb differ
diff --git a/test/data/grib_testfile03_info_ref b/test/data/grib_testfile03_info_ref
new file mode 100644
index 0000000..ea78105
--- /dev/null
+++ b/test/data/grib_testfile03_info_ref
@@ -0,0 +1,2 @@
+    -1 :       Date     Time   Level Gridsize    Miss :     Minimum        Mean     Maximum : Parameter ID
+     1 : 1958-09-01 00:00:00       0    35718       0 :      94858.  1.0104e+05  1.0374e+05 : 151.128       
diff --git a/test/data/grib_testfile03_sinfo_ref b/test/data/grib_testfile03_sinfo_ref
new file mode 100644
index 0000000..3d91dd5
--- /dev/null
+++ b/test/data/grib_testfile03_sinfo_ref
@@ -0,0 +1,12 @@
+   File format : GRIB
+    -1 : Institut Source   Steptype Levels Num    Points Num Dtype : Parameter ID
+     1 : ECMWF    unknown  instant       1   1     35718   1  P16  : 151.128       
+   Grid coordinates :
+     1 : gaussian reduced         : points=35718  nlat=160  np=80
+                              lat : 89.14152 to -89.14152 degrees_north
+   Vertical coordinates :
+     1 : surface                  : levels=1
+   Time coordinate :  1 step
+     RefTime =  1958-09-01 00:00:00  Units = hours  Calendar = proleptic_gregorian
+  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss
+  1958-09-01 00:00:00
diff --git a/test/data/griddes.icon_cell b/test/data/griddes.icon_cell
new file mode 100644
index 0000000..64f2069
--- /dev/null
+++ b/test/data/griddes.icon_cell
@@ -0,0 +1,174 @@
+#
+# gridID 1
+#
+gridtype  = unstructured
+gridsize  = 65
+xname     = clon
+xlongname = center longitude
+xunits    = radian
+yname     = clat
+ylongname = center latitude
+yunits    = radian
+nvertex   = 3
+xvals     = 0.993894662193839 0.628318530717959 0.262742399242078 3.14159265358979 
+            -2.77601652211391 2.77601652211391 -2.25053172362976 -0.628318530717959 
+            -0.262742399242078 -0.993894662193839 0.628318530717959 0.340374571222605 
+            0.628318530717958 0.916262490213313 1.88495559215388 1.59701163265852 
+            1.88495559215388 2.17289955164923 3.14159265358979 2.85364869409444 3.14159265358979 
+            -2.85364869409444 -1.88495559215388 -2.17289955164923 -1.88495559215388 
+            -1.59701163265852 -0.628318530717959 -0.916262490213313 -0.628318530717958 
+            -0.340374571222605 1.25663706143592 1.54458102093127 1.25663706143592 
+            0.968693101940563 2.51327412287183 2.80121808236719 2.51327412287183 
+            2.22533016337648 -2.51327412287183 -2.22533016337648 -2.51327412287183 
+            -2.80121808236719 -1.25663706143592 -0.968693101940563 -1.25663706143592 
+            -1.54458102093127 0 0.287943959495354 0 -0.287943959495354 1.25663706143592 
+            0.891060929960037 1.6222131929118 2.51327412287183 2.14769799139595 2.87885025434771 
+            -2.51327412287183 -2.87885025434772 -2.14769799139595 -1.25663706143592 
+            -1.6222131929118 -0.891060929960037 0 -0.36557613147588 0.36557613147588 
+xbounds   = 0.628318530717959 1.25663706143592 1.25663706143592 
+            1.25663706143592 0.628318530717959 0 
+            0 0 0.628318530717959 
+            3.14159265358979 -2.51327412287183 2.51327412287183 
+            3.14159265358979 -2.51327412287183 -2.51327412287183 
+            2.51327412287183 2.51327412287183 3.14159265358979 
+            -2.51327412287183 -2.51327412287183 -1.88495559215388 
+            -0.628318530717959 0 -1.25663706143592 
+            -0.628318530717959 0 0 
+            -1.25663706143592 -1.25663706143592 -0.628318530717959 
+            0.628318530717959 0.314159265358979 0.942477796076938 
+            0.628318530717959 0 0.314159265358979 
+            0.314159265358979 0.628318530717959 0.942477796076938 
+            0.942477796076938 1.25663706143592 0.628318530717959 
+            1.88495559215388 1.5707963267949 2.19911485751286 
+            1.88495559215388 1.25663706143592 1.5707963267949 
+            1.5707963267949 1.88495559215388 2.19911485751286 
+            2.19911485751286 2.51327412287183 1.88495559215388 
+            3.14159265358979 2.82743338823081 -2.82743338823081 
+            3.14159265358979 2.51327412287183 2.82743338823081 
+            2.82743338823081 3.14159265358979 -2.82743338823081 
+            -2.82743338823081 -2.51327412287183 3.14159265358979 
+            -1.88495559215388 -2.19911485751286 -1.5707963267949 
+            -1.88495559215388 -2.51327412287183 -2.19911485751286 
+            -2.19911485751286 -1.88495559215388 -1.5707963267949 
+            -1.5707963267949 -1.25663706143592 -1.88495559215388 
+            -0.628318530717959 -0.942477796076938 -0.314159265358979 
+            -0.628318530717959 -1.25663706143592 -0.942477796076938 
+            -0.942477796076938 -0.628318530717959 -0.314159265358979 
+            -0.314159265358979 0 -0.628318530717959 
+            1.25663706143592 1.5707963267949 0.942477796076938 
+            1.25663706143592 1.88495559215388 1.5707963267949 
+            1.5707963267949 1.25663706143592 0.942477796076938 
+            0.942477796076938 0.628318530717959 1.25663706143592 
+            2.51327412287183 2.82743338823081 2.19911485751286 
+            2.51327412287183 3.14159265358979 2.82743338823081 
+            2.82743338823081 2.51327412287183 2.19911485751286 
+            2.19911485751286 1.88495559215388 2.51327412287183 
+            -2.51327412287183 -2.19911485751286 -2.82743338823081 
+            -2.51327412287183 -1.88495559215388 -2.19911485751286 
+            -2.19911485751286 -2.51327412287183 -2.82743338823081 
+            -2.82743338823081 3.14159265358979 -2.51327412287183 
+            -1.25663706143592 -0.942477796076938 -1.5707963267949 
+            -1.25663706143592 -0.628318530717959 -0.942477796076938 
+            -0.942477796076938 -1.25663706143592 -1.5707963267949 
+            -1.5707963267949 -1.88495559215388 -1.25663706143592 
+            0 0.314159265358979 -0.314159265358979 
+            0 0.628318530717959 0.314159265358979 
+            0.314159265358979 0 -0.314159265358979 
+            -0.314159265358979 -0.628318530717959 0 
+            1.25663706143592 0.628318530717959 1.88495559215388 
+            1.25663706143592 0.628318530717959 0.628318530717959 
+            1.88495559215388 1.88495559215388 1.25663706143592 
+            2.51327412287183 1.88495559215388 3.14159265358979 
+            2.51327412287183 1.88495559215388 1.88495559215388 
+            3.14159265358979 3.14159265358979 2.51327412287183 
+            -2.51327412287183 3.14159265358979 -1.88495559215388 
+            -2.51327412287183 3.14159265358979 3.14159265358979 
+            -1.88495559215388 -1.88495559215388 -2.51327412287183 
+            -1.25663706143592 -1.88495559215388 -0.628318530717959 
+            -1.25663706143592 -1.88495559215388 -1.88495559215388 
+            -0.628318530717959 -0.628318530717959 -1.25663706143592 
+            0 -0.628318530717959 0.628318530717959 
+            0 -0.628318530717959 -0.628318530717959 
+            0.628318530717959 0.628318530717959 0 
+yvals     = 0.723075379408535 1.2331053800287 0.723075379408535 0.918438187010528 
+            0.723075379408535 0.723075379408535 0.723075379408535 0.918438187010528 
+            0.723075379408535 0.723075379408535 0.188710530783562 0.336710713671639 
+            -0.125956662234605 0.336710713671639 0.188710530783562 0.336710713671639 
+            -0.125956662234605 0.336710713671639 0.188710530783562 0.336710713671639 
+            -0.125956662234605 0.336710713671639 0.188710530783562 0.336710713671639 
+            -0.125956662234605 0.336710713671639 0.188710530783562 0.336710713671639 
+            -0.125956662234605 0.336710713671639 -0.188710530783562 -0.336710713671639 
+            0.125956662234605 -0.336710713671639 -0.188710530783562 -0.336710713671639 
+            0.125956662234605 -0.336710713671639 -0.188710530783562 -0.336710713671639 
+            0.125956662234605 -0.336710713671639 -0.188710530783562 -0.336710713671639 
+            0.125956662234605 -0.336710713671639 -0.188710530783562 -0.336710713671639 
+            0.125956662234605 -0.336710713671639 -0.918438187010528 -0.723075379408535 
+            -0.723075379408535 -0.918438187010528 -0.723075379408535 -0.723075379408535 
+            -0.918438187010528 -0.723075379408535 -0.723075379408535 -0.918438187010528 
+            -0.723075379408535 -0.723075379408535 -0.918438187010528 -0.723075379408535 
+            -0.723075379408535 
+ybounds   = 0.553574358897045 0.463647609000806 1.01722196789785 
+            1.01722196789785 1.5707963267949 1.01722196789785 
+            1.01722196789785 0.463647609000806 0.553574358897045 
+            0.553574358897045 1.01722196789785 1.01722196789785 
+            0.553574358897045 0.463647609000806 1.01722196789785 
+            1.01722196789785 0.463647609000806 0.553574358897045 
+            1.01722196789785 0.463647609000806 0.553574358897045 
+            0.553574358897045 1.01722196789785 1.01722196789785 
+            0.553574358897045 0.463647609000806 1.01722196789785 
+            1.01722196789785 0.463647609000806 0.553574358897045 
+            0.553574358897045 0 0 
+            0.553574358897045 0.463647609000806 0 
+            0 -0.463647609000806 0 
+            0 0.463647609000806 0.553574358897045 
+            0.553574358897045 0 0 
+            0.553574358897045 0.463647609000806 0 
+            0 -0.463647609000806 0 
+            0 0.463647609000806 0.553574358897045 
+            0.553574358897045 0 0 
+            0.553574358897045 0.463647609000806 0 
+            0 -0.463647609000806 0 
+            0 0.463647609000806 0.553574358897045 
+            0.553574358897045 0 0 
+            0.553574358897045 0.463647609000806 0 
+            0 -0.463647609000806 0 
+            0 0.463647609000806 0.553574358897045 
+            0.553574358897045 0 0 
+            0.553574358897045 0.463647609000806 0 
+            0 -0.463647609000806 0 
+            0 0.463647609000806 0.553574358897045 
+            -0.553574358897045 0 0 
+            -0.553574358897045 -0.463647609000806 0 
+            0 0.463647609000806 0 
+            0 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 0 0 
+            -0.553574358897045 -0.463647609000806 0 
+            0 0.463647609000806 0 
+            0 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 0 0 
+            -0.553574358897045 -0.463647609000806 0 
+            0 0.463647609000806 0 
+            0 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 0 0 
+            -0.553574358897045 -0.463647609000806 0 
+            0 0.463647609000806 0 
+            0 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 0 0 
+            -0.553574358897045 -0.463647609000806 0 
+            0 0.463647609000806 0 
+            0 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 -1.01722196789785 -1.01722196789785 
+            -0.553574358897045 -0.463647609000806 -1.01722196789785 
+            -1.01722196789785 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 -1.01722196789785 -1.01722196789785 
+            -0.553574358897045 -0.463647609000806 -1.01722196789785 
+            -1.01722196789785 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 -1.01722196789785 -1.01722196789785 
+            -0.553574358897045 -0.463647609000806 -1.01722196789785 
+            -1.01722196789785 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 -1.01722196789785 -1.01722196789785 
+            -0.553574358897045 -0.463647609000806 -1.01722196789785 
+            -1.01722196789785 -0.463647609000806 -0.553574358897045 
+            -0.553574358897045 -1.01722196789785 -1.01722196789785 
+            -0.553574358897045 -0.463647609000806 -1.01722196789785 
+            -1.01722196789785 -0.463647609000806 -0.553574358897045 
diff --git a/test/data/griddes.r18x9 b/test/data/griddes.r18x9
new file mode 100644
index 0000000..e6f0fcc
--- /dev/null
+++ b/test/data/griddes.r18x9
@@ -0,0 +1,199 @@
+#
+# gridID 1
+#
+gridtype  = unstructured
+gridsize  = 88
+xname     = lon
+xlongname = longitude
+xunits    = degrees_east
+yname     = lat
+ylongname = latitude
+yunits    = degrees_north
+nvertex   = 4
+xvals     = 180 200 260 280 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 
+            300 320 340 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 300 
+            320 340 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 300 320 
+            340 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 300 320 340 
+            0 40 140 160 180 200 220 300 320 340 0 340 
+xbounds   = 170 190 190 170 
+            190 210 210 190 
+            250 270 270 250 
+            270 290 290 270 
+            -10 10 10 -10 
+            10 30 30 10 
+            30 50 50 30 
+            50 70 70 50 
+            70 90 90 70 
+            90 110 110 90 
+            110 130 130 110 
+            130 150 150 130 
+            150 170 170 150 
+            170 190 190 170 
+            190 210 210 190 
+            210 230 230 210 
+            230 250 250 230 
+            250 270 270 250 
+            270 290 290 270 
+            290 310 310 290 
+            310 330 330 310 
+            330 350 350 330 
+            -10 10 10 -10 
+            10 30 30 10 
+            30 50 50 30 
+            50 70 70 50 
+            70 90 90 70 
+            90 110 110 90 
+            110 130 130 110 
+            130 150 150 130 
+            150 170 170 150 
+            170 190 190 170 
+            190 210 210 190 
+            210 230 230 210 
+            230 250 250 230 
+            250 270 270 250 
+            270 290 290 270 
+            290 310 310 290 
+            310 330 330 310 
+            330 350 350 330 
+            -10 10 10 -10 
+            10 30 30 10 
+            30 50 50 30 
+            50 70 70 50 
+            70 90 90 70 
+            90 110 110 90 
+            110 130 130 110 
+            130 150 150 130 
+            150 170 170 150 
+            170 190 190 170 
+            190 210 210 190 
+            210 230 230 210 
+            230 250 250 230 
+            250 270 270 250 
+            270 290 290 270 
+            290 310 310 290 
+            310 330 330 310 
+            330 350 350 330 
+            -10 10 10 -10 
+            10 30 30 10 
+            30 50 50 30 
+            50 70 70 50 
+            70 90 90 70 
+            90 110 110 90 
+            110 130 130 110 
+            130 150 150 130 
+            150 170 170 150 
+            170 190 190 170 
+            190 210 210 190 
+            210 230 230 210 
+            230 250 250 230 
+            250 270 270 250 
+            270 290 290 270 
+            290 310 310 290 
+            310 330 330 310 
+            330 350 350 330 
+            -10 10 10 -10 
+            30 50 50 30 
+            130 150 150 130 
+            150 170 170 150 
+            170 190 190 170 
+            190 210 210 190 
+            210 230 230 210 
+            290 310 310 290 
+            310 330 330 310 
+            330 350 350 330 
+            -10 10 10 -10 
+            330 350 350 330 
+yvals     = -67.5 -67.5 -67.5 -67.5 -45 -45 -45 -45 -45 -45 -45 -45 -45 -45 -45 -45 
+            -45 -45 -45 -45 -45 -45 -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 
+            -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 -22.5 0 0 0 0 0 
+            0 0 0 0 0 0 0 0 0 0 0 0 0 22.5 22.5 22.5 22.5 22.5 22.5 22.5 22.5 22.5 
+            22.5 22.5 22.5 22.5 22.5 22.5 22.5 22.5 22.5 45 45 45 45 45 45 45 45 
+            45 45 67.5 67.5 
+ybounds   = -78.75 -78.75 -56.25 -56.25 
+            -78.75 -78.75 -56.25 -56.25 
+            -78.75 -78.75 -56.25 -56.25 
+            -78.75 -78.75 -56.25 -56.25 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -56.25 -56.25 -33.75 -33.75 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -33.75 -33.75 -11.25 -11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            -11.25 -11.25 11.25 11.25 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            11.25 11.25 33.75 33.75 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            33.75 33.75 56.25 56.25 
+            56.25 56.25 78.75 78.75 
+            56.25 56.25 78.75 78.75 
diff --git a/test/data/icon_cell_grid b/test/data/icon_cell_grid
new file mode 100644
index 0000000..7d1f762
Binary files /dev/null and b/test/data/icon_cell_grid differ
diff --git a/test/data/r18x9_grid b/test/data/r18x9_grid
new file mode 100644
index 0000000..e17cc57
Binary files /dev/null and b/test/data/r18x9_grid differ
diff --git a/test/data/tsformat1_ref b/test/data/tsformat1_ref
new file mode 100644
index 0000000..8038203
Binary files /dev/null and b/test/data/tsformat1_ref differ
diff --git a/test/threads.test.in b/test/threads.test.in
index dae35d1..d2a1d46 100644
--- a/test/threads.test.in
+++ b/test/threads.test.in
@@ -4,9 +4,9 @@ echo 1..1 # Number of tests to be executed.
 test -n "$CDO"      || CDO=cdo
 test -n "$DATAPATH" || DATAPATH=./data
 #
-CDOOUT=cout
-CDOERR=cerr
-FORMAT="-f srv -b 32"
+CDOOUT=cout$$
+CDOERR=cerr$$
+OFORMAT="-f srv -b 32"
 #
 IFILE=$DATAPATH/pl_data
 NTEST=1
@@ -19,9 +19,9 @@ function testfunc()
   echo "Running test: $NTEST - $CDOTEST"
 
   RFILE=$DATAPATH/thread${NTEST}_ref
-  OFILE=thread${NTEST}_res
+  OFILE=tsformat${NTEST}_res
 
-  CDOCOMMAND="$CDO $FORMAT $INSTR $IFILE $OFILE"
+  CDOCOMMAND="$CDO $OFORMAT $INSTR $IFILE $OFILE"
       
   echo "$CDOCOMMAND"
 
diff --git a/test/tsformat.test.in b/test/tsformat.test.in
new file mode 100644
index 0000000..bb66643
--- /dev/null
+++ b/test/tsformat.test.in
@@ -0,0 +1,94 @@
+#! @SHELL@
+echo 1..8 # Number of tests to be executed.
+#
+test -n "$CDO"      || CDO=cdo
+test -n "$DATAPATH" || DATAPATH=./data
+#
+CDOOUT=cout$$
+CDOERR=cerr$$
+OFORMAT="-f srv -b 32"
+FORMATS="srv ext ieg grb grb2 nc nc2 nc4"
+#FORMATS="nc4"
+#
+IFILE=$DATAPATH/pl_data
+NTEST=1
+#
+function fileformat()
+{
+  FILEFORMAT=undefined
+  ENABLE_TEST=yes
+
+  if [ "${FORMAT}" = srv  ] ; then  FILEFORMAT=SERVICE;  fi
+  if [ "${FORMAT}" = ext  ] ; then  FILEFORMAT=EXTRA;    fi
+  if [ "${FORMAT}" = ieg  ] ; then  FILEFORMAT=IEG;      fi
+  if [ "${FORMAT}" = grb  ] ; then  FILEFORMAT=GRIB;     fi
+  if [ "${FORMAT}" = grb2 ] ; then  FILEFORMAT=GRIB_API; fi
+  if [ "${FORMAT}" = nc   ] ; then  FILEFORMAT=netCDF;   fi
+  if [ "${FORMAT}" = nc2  ] ; then  FILEFORMAT=netCDF2;  fi
+  if [ "${FORMAT}" = nc4  ] ; then  FILEFORMAT=netCDF4;  fi
+
+  if [ "@ENABLE_SERVICE@" = no -a "${FORMAT}" = srv  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_EXTRA@" = no   -a "${FORMAT}" = ext  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_IEG@" = no     -a "${FORMAT}" = ieg  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_GRIB@" = no    -a "${FORMAT}" = grb  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_GRIBAPI@" = no -a "${FORMAT}" = grb2 ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_NETCDF@" = no  -a "${FORMAT}" = nc   ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_NETCDF@" = no  -a "${FORMAT}" = nc2  ] ; then  ENABLE_TEST=no; fi
+  if [ "@ENABLE_NC4@" = no     -a "${FORMAT}" = nc4  ] ; then  ENABLE_TEST=no; fi
+}
+#
+function testfunc()
+{
+  RSTAT=0
+
+  CDOTEST="chaining set $INSET with $FILEFORMAT"
+  echo "Running test: $NTEST - $CDOTEST"
+
+  RFILE=$DATAPATH/tsformat${INSET}_ref
+  OFILE=thread${NTEST}_res
+
+  CDOCOMMAND="$CDO $INSTR ${IFILE}(${FORMAT}) $OFILE"
+      
+  echo "$CDOCOMMAND"
+
+  if [ "${ENABLE_TEST}" = yes ] ; then
+    if [ "@ENABLE_THREADS@" = yes ] ; then
+      $CDO -f $FORMAT setgrid,r12x6 ${IFILE} ifile$$
+      CDOCOMMAND="$CDO $INSTR ifile$$ $OFILE"
+
+      for i in {1..5} ; do
+        $CDOCOMMAND
+        test $? -eq 0 || let RSTAT+=1
+      done
+
+      $CDO diff -selcode,130 $RFILE $OFILE > $CDOOUT 2> $CDOERR
+      test $? -eq 0 || let RSTAT+=1
+      test -s $CDOOUT && let RSTAT+=1
+      cat $CDOOUT $CDOERR
+
+      rm -f $OFILE ifile$$
+
+      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 threads not enabled"
+    fi
+  else
+    test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP $FILEFORMAT not enabled"
+  fi
+  
+  let NTEST+=1
+  rm -f $OFILE
+}
+#
+for FORMAT in $FORMATS; do
+  fileformat
+#  INSTR="-fldmin -timmean -select,code=129,130,152"
+  INSTR="-fldmin -timmean -select,code=130"
+  INSET=1
+  testfunc
+done
+#
+rm -f $CDOOUT $CDOERR
+#
+exit 0
diff --git a/test/wildcard.test.in b/test/wildcard.test.in
index 67e1248..4387360 100644
--- a/test/wildcard.test.in
+++ b/test/wildcard.test.in
@@ -23,8 +23,8 @@ else
   IFILES="$IFILE1"
 fi
 #
-CDOOUT=cout
-CDOERR=cerr
+CDOOUT=cout$$
+CDOERR=cerr$$
 #
 NTEST=1
 #

-- 
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